Given the following base class:
class Base {
int a, b;
public:
Base(int a, int b=42): a(a), b(b) { }
};
And a class that is derived from base:
class Derived: public Base {
using Base::Base; // inherit Base constructors
bool c;
public:
Derived(int a): Base(a), c(true) { }
Derived(int a, int b): Base(a, b), c(true) { }
};
Is there a way to avoid having to create two separate constructors for Derived and instead overload the inherited Base constructors to initialize the extra member of Derived?
I was thinking to use something like this:
template <typename... Args,
typename std::enable_if_t<std::is_constructible_v<Base, Args&&...>, int> = 0>
explicit Derived(Args&&... args):
Base(std::forward<Args>(args)...), c(true) {}
This is close, but is too verbose and does not work if the the base class's constructors are inherited. i.e. if using Base::Base is present in the class (then it defaults to those constructors and does not initialize the field b).
It works if the base class inherited constructors are not present i.e. removing using Base::Base.
Is this the only way to have this work? i.e. by removing using Base::Base and using a variadic template constructor in each derived class? Is there a less verbose way to overload the inherited constructors?
I am using C++17.
In this case all you need to do is provide c with an in class initializer
class Derived : public Base {
using Base::Base;
bool c = true;
};
allows you to use Base's constructors and will initialize c to true in all cases.
It seems like what you're looking for is a way to inherit Base's constructors while just initializing members of Derived to something specific. For that, we can use a default member initializer:
class Derived: public Base {
public:
using Base::Base;
private:
bool c = true;
};
Constructing a Derived(42) will invoke the Base(int) constructor, but also initialize c to true.
Related
Why does this code:
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
};
int main(void)
{
B *b = new B(5);
delete b;
}
Result in these errors:
main.cpp: In function ‘int main()’:
main.cpp:13: error: no matching function for call to ‘B::B(int)’
main.cpp:8: note: candidates are: B::B()
main.cpp:8: note: B::B(const B&)
Shouldn't B inherit A's constructor?
(this is using gcc)
If your compiler supports C++11 standard, there is a constructor inheritance using using (pun intended). For more see Wikipedia C++11 article. You write:
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
using A::A;
};
This is all or nothing - you cannot inherit only some constructors, if you write this, you inherit all of them. To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them.
Historically constructors could not be inherited in the C++03 standard. You needed to inherit them manually one by one by calling base implementation on your own.
For templated base classes, refer to this example:
using std::vector;
template<class T>
class my_vector : public vector<T> {
public:
using vector<T>::vector; ///Takes all vector's constructors
/* */
};
Constructors are not inherited. They are called implicitly or explicitly by the child constructor.
The compiler creates a default constructor (one with no arguments) and a default copy constructor (one with an argument which is a reference to the same type). But if you want a constructor that will accept an int, you have to define it explicitly.
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
public:
explicit B(int x) : A(x) { }
};
UPDATE: In C++11, constructors can be inherited. See Suma's answer for details.
This is straight from Bjarne Stroustrup's page:
If you so choose, you can still shoot yourself in the foot by inheriting constructors in a derived class in which you define new member variables needing initialization:
struct B1 {
B1(int) { }
};
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x;
};
void test()
{
D1 d(6); // Oops: d.x is not initialized
D1 e; // error: D1 has no default constructor
}
note that using another great C++11 feature (member initialization):
int x = 77;
instead of
int x;
would solve the issue
You have to explicitly define the constructor in B and explicitly call the constructor for the parent.
B(int x) : A(x) { }
or
B() : A(5) { }
How about using a template function to bind all constructors?
template <class... T> Derived(T... t) : Base(t...) {}
Correct Code is
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
public:
B(int a):A(a){
}
};
main()
{
B *b = new B(5);
delete b;
}
Error is b/c Class B has not parameter constructor and second it should have base class initializer to call the constructor of Base Class parameter constructor
Here is how I make the derived classes "inherit" all the parent's constructors. I find this is the most straightforward way, since it simply passes all the arguments to the constructor of the parent class.
class Derived : public Parent {
public:
template <typename... Args>
Derived(Args&&... args) : Parent(std::forward<Args>(args)...)
{
}
};
Or if you would like to have a nice macro:
#define PARENT_CONSTRUCTOR(DERIVED, PARENT) \
template<typename... Args> \
DERIVED(Args&&... args) : PARENT(std::forward<Args>(args)...)
class Derived : public Parent
{
public:
PARENT_CONSTRUCTOR(Derived, Parent)
{
}
};
derived class inherits all the members(fields and methods) of the base class, but derived class cannot inherit the constructor of the base class because the constructors are not the members of the class. Instead of inheriting the constructors by the derived class, it only allowed to invoke the constructor of the base class
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
B(int x):A(x);
};
int main(void)
{
B *b = new B(5);
delete b;
}
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.
Is it possible to design a class that will inherit from any one of a group of base classes? I would like to be able to write something like:
class Derived : public ArbitraryBase {
public:
Derived () : ArbitraryBase () {}
...
};
where ArbitraryBase can be some base class determined at compile time. I have a group of base classes that I would like to derive identical classes from. Is there a way to avoid writing an individual derived class for each of the base classes?
If it is truly determined at compile time, you can make your derived class a template:
template<class T>
class Derived : public T {
public:
Derived() {}
...
};
You can later create instantiate this class by providing the base type:
int main() {
Derived< ??? > my_object;
...
}
Where ??? is some compile time way of getting your derived type.
You can do this via a template. Using
template<typename T>
class Derived : public T
{
public:
Derived() : T() {}
// or just use if actually need to provide a default constructor
Derived() = default;
};
gives you a class that inherits from T and calls T's default constructor. You would create a concrete class with it like
Derived<Base1> d;
and now d is a Derived that inherits from Base1.
If you need to inherit from an arbitrary number of bases then you can use a variadic template like
template<typename... Bases>
class Derived : public Bases...
{
public:
Dervied() : Bases()... {}
// or just use if actually need to provide a default constructor
Derived() = default;
};
and it would be used like
Derived<Base1, Base2, ..., BaseN> d;
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.
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.