I am trying to inherit a constructor from a base class, but I am getting the error: C2876: 'Poco::ThreadPool' : not all overloads are accessible.
namespace myNamespace{
class ThreadPool : public Poco::ThreadPool{
using Poco::ThreadPool::ThreadPool; // inherits constructors
};
}
Poco::ThreadPool has 3 constructors, 2 public ones both with default initialised arguments, and 1 private one.
How can I only inherit the public constructors?
I am not using c++11.
If you are not using C++11 or later, you can't inherit all base constructors with a single using declaration.
The old way pre-C++11 was to create a corresponding c'tor in the derived class for every c'tor in the base we wanted to expose. So for example:
struct foo {
int _i;
foo(int i = 0) : _i(i) {}
};
struct bar : private foo {
bar() : foo() {} // Use the default argument defined in foo
bar(int i) : foo(i) {} // Use a user supplied argument
};
If you still want to have a c'tor with a default argument, you can do that too:
struct baz : private foo {
baz(int i = 2) : foo(i) {} // We can even change what the default argument is
};
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;
}
Is it necessary to call parent constructor with no arguments from child class constructor?
If I have a class A:
class A {
public:
A() : value(100) { }
int get_value() { return value; }
private:
int value;
};
And a class B that inherets from A:
class B : public A {
public:
B() : A() {}
};
Will the constructor of A be called when initializing an object of B even if I do not have: B() : A() {} and the value set to 100?
Will the constructor of A be called when initializing an object of B even if I do not have: B() : A() {} and the value set to 100?
Yes.
Just like a member, if a base sub-object does not have an initialiser, it will be default-initialised. Default initialising A calls the user declared constructor.
You don't even need to declare the contsructor of B. The implicitly generated one does the same thing:
class B : public A {};
I have something that looks like this:
class Foo
{
public:
Foo(parameter);
}
class Bar
{
Foo fooObject;
}
Bar::fooObject(data);
But I get:
error: expected constructor, destructor, or type conversion before '(' token
So my question is: how do I construct fooObject from outside Bar?
You can have a constructor that take an instance of Foo from outside of class and then you can copy or move that instance to your member variable. Another approach would be to take required parameters to construct an instance of Foo and then use member initializer list to construct member variable.
class Bar
{
public:
Bar(const Foo& foo) // Copy
: fooObject(foo)
{
}
Bar(Foo&& foo) // Move
: fooObject(std::move(foo))
{
}
Bar(int example)
: fooObject(example)
{
}
private:
Foo fooObject;
}
Initialize members using a constructor and member initializer list:
class Foo{
public:
Foo(int x);
};
class Bar{
public:
Bar(int param);
private:
Foo fooObject;
};
Bar::Bar(int param) : fooObject(param){};
If by outside of the class you mean the class member function definition then you would use the following syntax that goes into a source (.cpp) file:
Bar::Bar(int param) : fooObject(param){}; // ctor definition outside the class
The declarations can be placed in a header file.
I have a question about default constructor on inherited class when the parent one is protected, in my mind the child class will have a default one protected too, but it's not the case.
Is there's a way to force the default constructor to be protected other than force it on child class ?
C++11 - gcc version 5.3.1 20151219 (Debian 5.3.1-4).
int main ( int argc, char ** argv )
{
using namespace std;
class A
{
public:
static std::shared_ptr<A> CreateInstance ()
{
A * pInstance { new A };
return { pInstance, []( A * pInstance )
{
delete pInstance;
}};
};
protected:
A () = default;
~A () = default;
};
class B : public A
{
};
B b; // It's work !
return 0;
}
Thanks for your help,
WCdr
No, a derived class' automatically-generated default constructor will still be public even if the base class constructor is protected.
There are two ways (I can think of) to prevent derived class B from being directly instantiable:
1. Remove the default constructor in class A
This can be accomplished by providing a constructor that takes a dummy argument:
class A
{
public:
// ...
protected:
A (int) {}
};
class B : public A
{
};
B b; // error: B::B()' is implicitly deleted because the
// default definition would be ill-formed
Instantiating B will fail, because B's automatically-generated default constructor will attempt to use A's default constructor, which does not exist.
But this is easily circumvented:
class B : public A
{
public:
B() : A(0) {}
}
B b; // works
2. Force the derived class' constructor to be protected
class B
{
// ...
protected:
B() = default;
}
Option (2) will be the least surprising to others reading your code, and is the option that I recommend. Anyone familiar with static createFoo factory functions will understand why the constructor is made private or protected.
EDIT
When using static create factory functions in a class hierarchy, the common idiom is for derived classes to also provide static create factory functions, and make their constructor private or protected.
Derived classes should not use the create factory function of the base class. They should invoke base class constructor, either implicitly or explicitly.
class Base
{
public:
static shared_ptr<Base> create()
{
return shared_ptr<Base>(new Base);
}
protected:
Base() {...}
};
class Derived
{
public:
static shared_ptr<Derived> create()
{
return shared_ptr<Derived>(new Derived);
}
protected:
Derived() {...} // Implicitly calls base class default constructor
};
// Usage
auto b = Base::create();
auto d = Derived::create();
I have a class like this:
//class1.h
class Foo
{
private:
int m_Value;
public:
int Foo();
}
//class1.cpp
#include "class1.h"
#define CONST_VARIABLE 12
Foo::Foo()
{
m_Value = CONST_VARIABLE;
}
and a derived class:
//class2.h
#include "class1.h"
class Foo2 : public Foo
{
puplic:
Foo2();
//other functions here
}
//class2.cpp
#define CONST_VARIABLE 24;
#include "class2.h"
Foo2::Foo2() : Foo()
{
}
However, when I called
Foo a;
Foo2 b;
Those 2 (a and b) have the same m_Value (which is 12).
I knew Foo2() will call Foo() first so m_Value will take the CONST_VARIABLE in class Foo. Thus, I try re-define it but with no luck.
Since both classes are initialized the same way but with different default values and I can't add parameter to the default constructor.
How can I create a derived class with same default constructor but with different value? And in the long run, I could easily maintain or modify the code by changing the the value quickly.
You could use a protected constructor so that only derived classes can use the constructor specifying a different member value:
class Foo {
public:
Foo();
protected:
explicit Foo(int value);
private:
int m_Value;
};
Foo::Foo() :
m_Value(12)
{}
Foo::Foo(int value) :
m_Value(value)
{}
class Foo2 {
public:
Foo2();
};
Foo2::Foo2 :
Foo(24)
{}
Adhering to your requirement that there is only a default constructor, you can accomplish that with a template. Assuming you have full control over your implementation:
template <int CONST_VALUE>
class FooT {
protected:
int m_Value;
FooT () : m_Value(CONST_VALUE) {}
};
class Foo : FooT<12> {
//...
};
class Foo2 : FooT<24> {
//...
};
If Foo2 must inherit from Foo directly, you can move the parts that need to be initialized into a super parent class, and then use virtual inheritance of it by Foo so that Foo2 can initialize the super parent directly. This avoids needing to implement two constructors in Foo (one default one, and one to let Foo2 dictate initialization).
class FooBase {
protected:
int m_Value;
FooBase (int v) : m_Value(v) {}
};
class Foo : public virtual FooBase {
public:
Foo () : FooBase(12) {}
//...
};
class Foo2 : public Foo {
public:
Foo2 () : FooBase(24) {}
//...
};