class declaration

i was just wanna create header file just for fun, but then, something weird happened:

i will just give all of my codes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//header
#ifndef __mnemonic__
#define __mnemonic__

class mnemonic_one {
	int id;
	bool cond;
	char opsign;

public:
	int print_mnemonic();
	mnemonic_one();
	mnemonic_one(int, bool, char);
};

mnemonic_one::mnemonic_one(void) {
	id = 0;
	cond = true;
	opsign = '+';
}

mnemonic_one::mnemonic_one(int ID = 0, bool COND = true, char OPSIGN = '+') {
	id = ID;
	cond = COND;
	opsign = OPSIGN;
}

int mnemonic_one::print_mnemonic(void) {
	return id;
}
#endif 



1
2
3
4
5
6
7
8
9
10
11
12
//main
#include <iostream>
#include "mnemonic.h"

int main() {
	mnemonic_one one_var;
	std::cout << one_var.print_mnemonic() << std::endl;
	std::cout << "press ENTER to exit from the program...";
	std::cin.ignore(std::numeric_limits<int>::max(), '\n');
	std::cin.get();
	return 0;
}


error message:
Error C2668 'mnemonic_one::mnemonic_one': ambiguous call to overloaded function


am i missing something?
Line 16: This is a default constructor with no arguments.
Line 22: This constructor has three arguments. All have defaults values, which means it is legal to call this constructor with no arguments.

Line 6: You instantiate mnemonic_one with no arguments. Which constructor is the compiler supposed to call? The default constructor, or the one with all three arguments defaulted?

Two possible solutions:
1) Change line 22 so that ID is not defaulted. That will make the constructors different enough so the compiler will know which one you want.
2) Get rid of the default constructor.
Last edited on
why i should get rid of it? wasn't it legal?
> #ifndef __mnemonic__

Avoid this.
some identifiers are reserved for use by C ++ implementations and shall not be used otherwise; no diagnostic is required.

Each identifier that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.

Each identifier that begins with an underscore is reserved to the implementation for use as a name in the global namespace.



Member functions defined in the header, outside the class definition should be declared inline Otherwise, there would be an ODR violation if the header is included in more than one translation unit.
One Definition Rule: http://en.cppreference.com/w/cpp/language/definition


The rules for function overload resolution apply for selecting the constructor of a class.
If a class has more than one default constructor, default initialisation of an object would be ambiguous.
For instance:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct A
{
    static A sa ;
    A() ; // (1) default constructor
    A( int = 8, bool = true ) ; // (2) default constructor
    A( const A& = sa, int = 99 ) ; // (3) default constructor, copy constructor
};

int main() //
{
    A a1(45) ; // fine: constructor (2)
    A a2(a1) ; // fine: copy constructor: constructor (3)
    A a3( 45, false ) ; // fine: constructor (2)
    A a4( a3, 78 ) ; // fine: constructor (3)

    A a5 ; // *** error *** ambiguous: constructors (1), (2) and (3) are all viable candidates
}

http://coliru.stacked-crooked.com/a/e3ca1137d1cd3c53
you mean even if i use default constructor without parameter and i create the other one with parameter(s), it would become ambiguous?
The problem is that you have specified a default argument for all parameters in the other constructor. If some of the arguments are left out the default arguments will be passed instead. When you do not specify any of the arguments the compiler don't know which constructor to use.

1
2
3
4
5
6
7
8
9
10
11
12
// Calls mnemonic_one(2, false, '?')
mnemonic_one(2, false, '?');

// Calls mnemonic_one(2, false, '+')
mnemonic_one(2, false);

// Calls mnemonic_one(2, true, '+')
mnemonic_one(2);

// What should this call? mnemonic_one(0, true, '+') or mnemonic_one()?
// The compiler doesn't know so it gives an error.
mnemonic_one();
Last edited on
why don't it just take the default constructor with no parameter?

like in here (Overloading constructors topic):
http://www.cplusplus.com/doc/tutorial/classes/
In the tutorial example there is only one constructor that match when no arguments are passed so there is no ambiguity. In your example there are two constructors that match.

If it called the constructor with no parameters in this situation it would mean that the default argument for ID is useless, and would never be used.

The solution to your problem is very simple. Just leave out the default argument for ID.

 
mnemonic_one(int ID, bool COND = true, char OPSIGN = '+')

A default argument only makes sense if you want the constructor to be called when the argument is left out. You are obviously saying you don't want this constructor to be called when ID is left out so then ID should not have a default argument.
Last edited on
you mean, if we wrote:
mnemonic_one dummy1();
is the same with
mnemonic_one dummy1(0);
?
btw, i have another question, why this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>
#include "mnemonic.h"
#include "execs.h"

class dummy {
	int d1;

public:
	
	dummy() {
		d1 = 3;
	}

	dummy(int prmtr = 0) {
		d1 = prmtr;
	}
	void prnt() {
		std::cout << d1;
		return;
	}
};
int main() {
	dummy dumb1();
	dumb1.prnt();
	std::cout << std::endl;
	std::cin.get();
	return 0;
}


gives the error message:
left of '.prnt' must have class/struct/union

and not gives the error that says the constructor is having ambiguity?
dummy dumb1(); declares a function named 'dumb1' with the return type 'dummy'

Most vexing parse: https://en.wikipedia.org/wiki/Most_vexing_parse
http://coliru.stacked-crooked.com/a/05effed3b15adb96
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <string>

class dummy
{
private:
	int d1;

public:	
	dummy(int prmtr = 3) { d1 = prmtr; }
	void print();
};
	
void dummy::print()
{
   std::cout << d1 << std::endl;
   return;
}
	
int main() {
	dummy dumb1;
	dumb1.print();
	
	dummy dumb2(3);
	dumb2.print();
	
	return 0;
}
3
3
 
Exit code: 0 (normal program termination)
Last edited on
correction:
you mean, if we wrote:
mnemonic_one dummy1();
is the same with
mnemonic_one dummy1(0);
?


i mean mnemonic_one dummy1;
1
2
3
4
5
6
7
8
9
10
11
12
class mnemonic_one { public: mnemonic_one( int = 0 ) { /* ... */ } /* .. */ } ;


mnemonic_one dummy1 ; // defines default-initialised object dummy1

mnemonic_one dummy2{} ; // defines value-initialised object dummy2

mnemonic_one dummy3(0) ; // defines object dummy3 constructed with mnemonic_one::mnemonic_one(int)

mnemonic_one dummy4{0} ; // defines object dummy4 constructor: mnemonic_one::mnemonic_one(int)

mnemonic_one dummy5() ; // declares function dummy5 
Topic archived. No new replies allowed.