Can you tell me what is wrong in the following example? I am using C++17, where I thought the following should be supported.
class Base {
public:
virtual ~Base() = default;
};
struct Derived : public Base {
int m1;
};
int main() {
/* Results in a compilation error
* error C2440: 'initializing': cannot convert from 'initializer list' to 'Derived'
* message : No constructor could take the source type, or constructor overload resolution was ambiguous */
Derived d{ {},1 };
return 0;
}
It does not work because Derived is not an aggregate since it has a base class with virtual members.
The code compiles and runs when removing the virtual destructor in Base and using C++17.
If Base requires a virtual destructor, Derived can implement a custom constructor allowing initialization using curly brackets.
class Base {
public:
virtual ~Base() = default;
};
struct Derived : public Base {
Derived(int m): m1(m) {}
int m1;
};
int main() {
Derived d{ 1 };
return 0;
}
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 have several c++ classes that have similar behaviours. Moreover most of the class methods can be constructed from few fundamental ones. So I want to define a base class with the derived methods, inherit from the base class and define the remaining methods in the derived classes.
This is my attempt using the CRTP
template <class derived_class> class base_class {
public:
virtual derived_class& operator++ () = 0;
virtual derived_class& fun1() = 0;
derived_class operator++ (int) {
derived_class toreturn(static_cast<derived_class&>(*this));
++*this;
return toreturn;}
derived_class& fun2() {
this->fun1();
return static_cast<derived_class&>(*this);
};
};
class deriv1 : public base_class<deriv1> {
public:
int n;
deriv1():n(0){};
deriv1(deriv1& other):n(other.n){};
deriv1& operator++ () override { ++n; return *this;}
deriv1& fun1() override { n *= n; return *this;}
};
I don't understand why fun2() works but not the postscript increment.
If I call the postscript increment on a derived object I get the error message "Cannot increment value of type 'deriv1'".
The solution is to add a using statement:
class deriv1 : public base_class<deriv1> {
public:
....
using base_class::operator++;
};
The problem is that function resolution is failing. Lets think of a simpler solution to illustrate the problem:
struct Base
{
void f() {}
void f(int) {}
};
struct Derived: public Base
{
void f() {}
};
int main()
{
Derived a;
a.f(1); // This fails as there is no f() that takes an integer
// in Derived. And since the compiler found an f() in
// Derived it stopped looking further up the chain
// for additional matches.
}
This problem is solved in the same way.
struct Derived: public Base
{
using Base::f;
void f() {}
};
I know it's OK to call base class function in a derived class constructor, because base class is constructed before derived class.But I'm not sure if this is a good practice.Example code is:
class Base {
public:
int Get() const { return i_; }
void Set(const int i) { i_ = i; }
private:
int i_{0};
};
class Derived : public Base {
// initialize `derived_i_` with a call to base class function, Is this a good
// practice in production code?
Derived() : derived_i_{Get()} {
// do some other things
}
private:
int derived_i_{0};
};
To be more pedantic, you could write your constructor as the following:
Derived() : Base(), derived_i_{Get()} {
// do some other things
}
The compiler should fully construct the base class before doing any initialization of the derived class.
In my problem, I will have a few classes that will share getters and setters (in my case, the operator()). Suppose I have the following
class Base
{
public:
int& operator()() { return value; }
int operator()() const { return value; }
protected:
int value;
};
class Derived : public Base
{
public:
int operator()() const { return value; }
};
I expected being able to do something like this :
Derived d;
d() = 1;
but the compiler complains saying that the expression is not assignable. However, doing this
Derived d;
d.Base::operator()() = 1;
works correctly. Why is that ? Shouldn't the compiler be able to look up for the member function in the base class ? Is there a solution to avoid rewriting the non-const method is the derived class ?
Shouldn't the compiler be able to look up for the member function in the base class?
Yes, it is possible, but you have to be explicit. For that you can use a using declaration, which introduces the operator to the derived class:
class Derived : public Base
{
public:
using Base::operator();
int operator()() const { return value; }
};