Passing the derived class constructor parameter to a protected member - c++

I'm trying to practice some polymorphism and i got into some issues.
Here's my code :
class A{ //the base
public:
A(){}
virtual void Log(){};
virtual ~A(){};
private:
protected:
int __value;
};
class B : public A{ //the derived
public:
B(int value):__value(value){} //here's the problem
void Log() override{
std::cout<<__value<<"\n";
}
~B(){};
};
At that lines the error said : "class 'B' does not have any field named '__value'". It does work if i will do it in this way :
class A{
public:
A(){}
virtual void Log(){};
virtual ~A(){};
private:
protected:
int __value;
};
class B : public A{
public:
B(int value){
__value=value;
}
void Log() override{
std::cout<<__value<<"\n";
}
~B(){};
};
I know what i've tried works while i'm accesing the private members, but I want to know if there is some way to make the first attempt work too.
Thanks!

C++ does not work this way. Only a class's constructor can initialize its members.
Only A's constructor can initialize its class member. That's what a constructor's job is. A derived class cannot initialize its base class's members, only it's own class members. A base class only initializes the base class's members. A derived class's constructor can initialize only its own class's members.
What you need to do is add a constructor to A, perhaps a protected constructor, with a parameter that initializes the class member with the parameter:
class A {
// ...
A(int value) : __value{value} {}
// ...
};
And have the derived class's constructor explicitly invoke this constructor.
B(int value) : A{value}
{
}
In some situations you can also delegate the constructor, as an alternative. This should be covered in the advanced C++ chapters of your C++ book.
P.S. You should use modern C++'s uniform initialization syntax, with {...} instead of (...). If you're using an older C++ book that doesn't cover uniform initialization syntax, you should get a more recent book.

Related

Call base class constructor after member constructor

I have the following class hierarchy, where the Base class depends on its derived class to supply it an argument in its constructor:
class Member
{
public:
Member(int v);
};
class Base
{
public:
Base(const Member& m);
};
class Derived : public Base
{
public:
Derived() : m_(123), Base(m_) // <- here is the problem
{
}
private:
Member m_;
};
The problem is, though, that in Derived's constructor, the Base constructor gets called first, when Derived's member variable m_ which it depends on isn't initialized yet.
Is there a way to force the compiler to call the constructor of m_ first or should I just rework my class hierarchy?
You can simulate initializing your member before the base class by making it it's own base class which you initialize first. You can wrap it in a simple class type and have Derived inherit privately from that type before Base. In the following example, Derived has a Member _m; which is initialized and then used to initialize Base.
class Member
{
public:
Member(int) {}
};
class Base
{
public:
Base(const Member&) {}
};
// The new wrapper
struct member_wrapper
{
member_wrapper(int v) : m_(v) {}
Member m_;
};
class Derived : private member_wrapper, public Base
{
public:
Derived() : member_wrapper(123), Base(m_)
{ }
};
Though in this case, since m_ is already a class type and Derived has no other members with that type, you can just inherit privately from Member directly. If you had a non-class type or multiple members of the same type that needed to be initialized before Base you would need to wrap them.
class Member
{
public:
Member(int) {}
};
class Base
{
public:
Base(const Member&) {}
};
class Derived : private Member, public Base
{
public:
Derived() : Member(123), Base(*this)
{ }
};

Initializer List for Derived Class

I want to have a derived class which has a default constructor that initializes the inheirited members.
Why can I do this
class base{
protected:
int data;
};
class derived: public base{
public:
derived(){ //note
data = 42;
}
};
int main(){
derived d();
}
But not this
class base{
protected:
int data;
};
class derived: public base{
public:
derived(): //note
data(42){}
};
int main(){
derived d();
}
error: class ‘derived’ does not have any field named ‘data’
An object can only be initialized once. (The exception is if you initialize it and then destroy it; then you can initialize it again later.)
If you could do what you're trying to do, then base::data could potentially be initialized twice. Some constructor of base might initialize it (although in your particular case it doesn't) and then the derived constructor would be initializing it, potentially for a second time. To prevent this, the language only allows a constructor to initialize its own class's members.
Initialization is distinct from assignment. Assigning to data is no problem: you can only initialize data once but you can assign to it as many times as you want.
You might want to write a constructor for base that takes a value for data.
class base{
protected:
int data;
base(int data): data(data) {}
};
class derived: public base{
public:
derived(): base(42) {}
};
int main(){
derived d{}; // note: use curly braces to avoid declaring a function
}
You need a base class constructor for this job. You can look for more explanation here -
Initialize parent's protected members with initialization list (C++)

Does C++ require you to initialize base class members from its derived class?

class Base {
public:
int a;
Base():a(0) {}
virtual ~Base();
}
class Derived : public Base {
public:
int b;
Derived():b(0) {
Base* pBase = static_cast<Base*>(this);
pBase->Base();
}
~Derived();
}
Is the call to the base class constructor necessary or does c++ do this automatically? e.g.
Does C++ require you to initialize base class members from any derived class?
The base class's constructor will automatically be called before the derived class's constructor is called.
You can explicitly specify which base constructor to call (if it has multiple) using initialization lists:
class Base {
public:
int a;
Base():a(0) {}
Base(int a):a(a) {}
};
class Derived {
public:
int b;
Derived():Base(),b(0) {}
Derived(int a):Base(a),b(0) {}
};
Base class constructors are called automatically (and before derived class contructors). So you need not, and must not, try to call base constructors manually.

sealed class implementation query

I was reading the C++ faqs on http://www2.research.att.com/~bs/bs_faq2.html , when i came accross this code to implement a 'sealed' class:
class Base{
public:
friend class A;
private:
Base(){cout<<"Base constructor called";}
};
class A : public virtual Base{
public:
A(){cout<<"A const called";}
};
class B : private A{};
int main(){
A a;
//B b;
return EXIT_SUCCESS;
}
I did not understand how by using the virtual keyword, 'sealed' class effect is achieved. If i remove the virtual keyword, then it has no 'sealed' effect. Why?
It works because due to the way virtual inheritance works, B must construct Base- which it can't, because Base's constructor is private. Only A can construct Base. In normal inheritance, B constructs A, which constructs Base, which is fine because A can construct Base and B can construct A.

Virtual Inheritance : Base Ctor not calling in Most Derived Class?

class Base
{
public:
Base(){}
Base(int k):a(k)
{
}
int a;
};
class X:virtual public Base
{
public:
X():Base(10){}
int x;
};
class Y:virtual public Base
{
public:
Y():Base(10){}
int y;
};
class Z:public X,public Y
{
public:
Z():X(10){}
};
int main()
{
Z a;
cout << a.a;
return 1;
}
In the above case, for Z():X(10){} Base(int k):a(k) is not calling, but when i change to Z():Base(10){} the Base(int k):a(k) is called. Why ?
Thank you.
Because you used the virtual keyword - that's exactly what it does.
You have to explicitly initialize Base in the initializer list of Z in order to disambiguate between the initialization in X and the initalization in Y.
See this question. The gist is, that when using virtual inheritance you have to call the base class constructor explicitly.
The initializer list in the most derived constructor is used to initialize your base classes. Since class Z inherits from class X and Y which inherits from a common base class, the virtual keyword is used to create only a single subobject for the base class in order to disambiguate when accessing the data member a.