Have a problem with multiple inheritance. I have solved diamond problem:
class A
{
int m;
int n;
public:
A(int x, int y)
{
m = x; n = y
}
fA() {}
};
class B : virtual public A // B has fA(),fB()
{
public:
B(int k) : A(1, k) {}
fB() {}
};
class C : virtual public A // C has fA(),fC()
{
public:
C(int k) : C(2, k) {}
fC() {}
};
class D : public B, public C // D has fA(),fB(),fC()
{
public:
D(int k) : B(k),C(k),A(3,k)
};
This is working well. Problem with this:
class S : public B // S has fA(),fB()
{
public:
S() : B(6) {}
};
Compilator shows me: "error: no matching function for call to `A::A()'"
This code is working, but it doesn't satisfied me:
class S : public B // S has fA(),fB()
{
public:
S() : B(6),A(1,6) {}
};
In virtual inheritance, the constructor of virtual base is called from the constructor of most derived class:
class S : public B // S has fA(),fB()
{
public:
S() : B(6) {}
}; // ^ A base class is initialized at this point, before B
This also means that other explicit calls to A's constructor in initialization-lists further down the inheritance chain are ignored:
class B : virtual public A // B has fA(),fB()
{
public:
B(int k) : A(1, k) {}
fB() {} // ^^^^^^^ this call is ignored when B is a part of S object
};
If there's no explicit call to virtual base's constructor in initialization list of most derived class, the compiler will (of course) try to call the default constructor. But A doesn't have one and that's your problem.
One solution you already discovered yourself. The other is to write default constructor for A.
Related
While working with templates I ran into a need to make a base class constructors accessible from inherited classes for object creation to decrease copy/paste operations.
I was thinking to do this through using keyword in same manner with functions case, but that not work.
class A
{
public:
A(int val) {}
};
class B : public A
{
};
class C : public A
{
public:
C(const string &val) {}
};
class D : public A
{
public:
D(const string &val) {}
using A::A; // g++ error: A::A names constructor
};
void main()
{
B b(10); // Ok. (A::A constructor is not overlapped)
C c(10); // error: no matching function to call to 'C::C(int)'
}
So my question: Is there any way to import a base class constructors after new ones in inherited class been declared?
Or there is only one alternative to declare new constructors and call a base ones from initializer list?
Yes, Since C++11:
struct B2 {
B2(int = 13, int = 42);
};
struct D2 : B2 {
using B2::B2;
// The set of inherited constructors is
// 1. B2(const B2&)
// 2. B2(B2&&)
// 3. B2(int = 13, int = 42)
// 4. B2(int = 13)
// 5. B2()
// D2 has the following constructors:
// 1. D2()
// 2. D2(const D2&)
// 3. D2(D2&&)
// 4. D2(int, int) <- inherited
// 5. D2(int) <- inherited
};
For additional information see http://en.cppreference.com/w/cpp/language/using_declaration
Prefer initialization:
class C : public A
{
public:
C(const string &val) : A(anInt) {}
};
In C++11, you can use inheriting constructors (which has the syntax seen in your example D).
Update: Inheriting Constructors have been available in GCC since version 4.8.
If you don't find initialization appealing (e.g. due to the number of possibilities in your actual case), then you might favor this approach for some TMP constructs:
class A
{
public:
A() {}
virtual ~A() {}
void init(int) { std::cout << "A\n"; }
};
class B : public A
{
public:
B() : A() {}
void init(int) { std::cout << "B\n"; }
};
class C : public A
{
public:
C() : A() {}
void init(int) { std::cout << "C\n"; }
};
class D : public A
{
public:
D() : A() {}
using A::init;
void init(const std::string& s) { std::cout << "D -> " << s << "\n"; }
};
int main()
{
B b; b.init(10);
C c; c.init(10);
D d; d.init(10); d.init("a");
return 0;
}
No, that's not how it is done. Normal way to initialize the base class is in the initialization list :
class A
{
public:
A(int val) {}
};
class B : public A
{
public:
B( int v) : A( v )
{
}
};
void main()
{
B b(10);
}
You'll need to declare constructors in each of the derived classes, and then call the base class constructor from the initializer list:
class D : public A
{
public:
D(const string &val) : A(0) {}
D( int val ) : A( val ) {}
};
D variable1( "Hello" );
D variable2( 10 );
C++11 allows you to use the using A::A syntax you use in your decleration of D, but C++11 features aren't supported by all compilers just now, so best to stick with the older C++ methods until this feature is implemented in all the compilers your code will be used with.
class A
{
public:
A(int val) {}
A(string name) {}
};
class B : public A
{
using A::A;
};
Addition to other answers, in case there are several constuctors with the base class, and you just want to inherit some of them, you can delete the unwanted.
class B : public A
{
using A::A;
B(string) = delete;
};
Here is a good discussion about superclass constructor calling rules. You always want the base class constructor to be called before the derived class constructor in order to form an object properly. Which is why this form is used
B( int v) : A( v )
{
}
I apologize if my question is dumb but i'm a beginner in c++. I'm working on diamond inheritance and i would like to know if it is possible to choose the specific parent class which will initilize an attribute for the child class.
To sum up, i would like this code to output B
Thank you for your answers !
PS: i'm working with c++98
#include <iostream>
class A
{
protected:
char m_char;
public:
A(): m_char('A'){};
char getChar(){return m_char;};
~A(){};
};
class B : virtual public A
{
private:
public:
B() {m_char = 'B';};
~B(){};
};
class C : virtual public A
{
private:
public:
C() {m_char = 'C';};
~C(){};
};
class D : public B, public C
{
private:
public:
D() {m_char = B::m_char;};
~D(){};
};
int main(void)
{
D d;
std::cout << d.getChar() << std::endl;
}
Virtual base classes are initialized In depth-first, left-to-right order. So you would need to name B second in your inheritance for D to call its constructor last and thus setting the variable to B at the end.
class D : public C, public B
m_char = B::m_char; is self assignment (there is only one m_char).
In virtual inheritance, it is the most derived class which initialize the virtual class (body does assignment).
How about being explicit in construction:
#include <iostream>
class A
{
protected:
char m_char;
public:
A() : m_char('A') {}
char getChar() const { return m_char; }
virtual ~A() {}
};
class B : virtual public A
{
public:
B() : A('B') {}
};
class C : virtual public A
{
public:
C() : A('C') {}
};
class D : public B, public C
{
public:
D() : A('B'), B(), C() {}
};
int main()
{
D d;
std::cout << d.getChar() << std::endl;
}
I have a question on how to use initializer list for constructors of a derived class that are inheriting from constructors of a base class.
This is the code that works:
class base {
public:
base():x(0) {}
base(int a):x(a) {}
private:
int x;
};
class derived : public base {
public:
derived():base():y(0) { y=0; }
derived(int a, int b):base(a) { y=b; }
private:
int y;
};
However, I want to use the member initializer list to initialize the variables directly, and this leads to an error:
class base {
public:
base():x(0) {}
base(int a):x(a) {}
private:
int x;
};
class derived : public base {
public:
//derived():base():y(0) {} //wrong
//derived(int a, int b):base(a):y(b) {} //wrong
derived():base(), y(0) {} // corrected
derived(int a, int b): base(a), y(b) {} //corrected
private:
int y;
};
What's the right syntax for constructors that inherits from another constructor to use initializer list?
Thanks :)
As noted by Dieter, you can easily have many initializers in a constructor, they simply must be separated with comma (,) instead of column (:).
You class derived should then be :
class derived : public base {
public:
derived():base(),y(0) {}
derived(int a, int b):base(a),y(b) {}
private:
int y;
};
derivedClass::derivedClass(argumentsSetOne, argumentsSetTwo, .....) : baseClassOne(argumentsSetOne) , baseClassTwo(argumentsSetTwo) { }
order doesn't really matter...by that i mean, you can specify argumentsSetTwo before argumentsSetOne in the Derived Class's Constructor's arguments field. But again it should be same as specified in the prototype....
I'm stuck with a program I'm writing after a while of fidling around and completing "c++ through game programming" book.
The situation is as follows:
Class A
{
public:
A(int x)
protected:
int a;
};
A::A(int x):
a(x)
{}
Class B : public A
Class C : public B
{
public:
C(int x)
};
C::C(int x)
{
A(int x);
}
Am I able to call the constructor of class A in the constructor of class C?
From what I think I know: B is linked to A and C is linked to B so I should be able to get to the constructor of class A from C when I am able to reach member variables and functions by derriving it.
You can either try this:
class B : public A
{
public:
B(int x) : A(x) { }
};
class C : public B
{
public:
C(int x) : B(x) { }
};
Or if you're lazy (and using C++11):
class B : public A
{
public:
using A::A(int);
};
class C : public B
{
public:
using B::B(int);
};
This won't work:
class C : public B
{
public:
C(int x) : A(x) { }
};
main.cpp: In constructor ‘C::C(int)’:
main.cpp:23:16: error: type ‘A’ is not a direct base of ‘C’
C(int x) : A(x) { }
^
main.cpp:23:19: error: use of deleted function ‘B::B()’
C(int x) : A(x) { }
Here is my issue. I want to have something like this:
class A {
protected:
int someInt;
virtual void someFunc() = 0;
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B() {//tell the A inside of B to set someInt to whatever it wants}
};
so basically, someInt can be changed, it's not constant, but I want all the classes that implement A to use a value provided by A for someInt.
Thanks
You can use initializer lists in the constructor to call parent constructors:
class A {
protected:
int someInt;
virtual void someFunc() = 0;
A(int x) : someInt(x) {} // Base-class constructor (initialises someInt)
};
class B : public A {
protected:
virtual void someFunc() {}
public:
B() : A(10) {} // Initialises base class via constructor
};
Is this what you want?
class A
{
protected:
int someInt;
public:
A(int _val) : someInt(_val)
{
}; // eo ctor
}; // eo class A
class B : public A
{
public:
B() : A(5) // initialise someInt with 5
{
}; // eo ctor
}; // eo class B
Note, that as "someInt" is protected, you can just set it in B's constructor anyway.
B()
{
A::someInt = 5;
}; // eo ctor
I am not sure what you want, but if you initialize someInt in the constructor of A, subclasses will see that value.
class A {
public:
A() : someInt(5) {}
protected:
int someInt;
virtual void someFunc() = 0;
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B() {// at this point someInt will already have been initialized to 5}
};
When the subclass is constructed, the baseclass constructors are executed first.
class A {
protected:
int someInt;
virtual void someFunc() = 0;
A(){//set someInt here}
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B():A() {}
};
A protected constructor will achieve this. As above. The solutions using a public constructor are fine too, but as the constructor cannot be called directly on thr interface I think protected is better.