Reputation: 4769
I want to use a base object that defines an "interface" and then have derived objects implement it. Every object is initialized with its name which is always the same process: Writing to a member "name_" with parameter passed to the constructor. I want to have derived objects behave exactly the same way as the base object in that regard, so every derived object should write to its name varialbe. However, the problem is that I would need to define an extra constructor in every derived object that writes to the name variable which is cumbersome. The following example does not compile because of this reason. Is there any way around this or is inheritance even the right approach (please feel free to suggest otherwise)?
Non-compiling code (shows what I want to do):
#include <iostream>
class A {
const std::string name_;
public:
A(const std::string name) : name_(name) { std::cout << "creation of object " << name_ << "; this name = " << this->name_ << '\n'; }
};
class B : public A {
// const std::string name_; -- we do not even need this because "name_" also exists for object B.
// C++ misses its constructor here :') - I don't
};
int main()
{
A obj_a{ "A" };
B obj_b{ "B" };
}
Associated error(s):
source>:20:18: error: no matching function for call to 'B::B(<brace-enclosed initializer list>)'
20 | B obj_b{ "B" };
| ^
<source>:12:7: note: candidate: 'B::B(const B&)'
12 | class B : public A {
| ^
<source>:12:7: note: no known conversion for argument 1 from 'const char [2]' to 'const B&'
<source>:12:7: note: candidate: 'B::B(B&&)'
<source>:12:7: note: no known conversion for argument 1 from 'const char [2]' to 'B&&'
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:20:18: error: no matching function for call to 'B::B(<brace-enclosed initializer list>)'
20 | B obj_b{ "B" };
| ^
<source>:12:7: note: candidate: 'B::B(const B&)'
12 | class B : public A {
| ^
<source>:12:7: note: no known conversion for argument 1 from 'const char [2]' to 'const B&'
<source>:12:7: note: candidate: 'B::B(B&&)'
<source>:12:7: note: no known conversion for argument 1 from 'const char [2]' to 'B&&'
Upvotes: 0
Views: 996
Reputation: 73186
You may use a using-declaration to
Using-declaration
[...] introduce base class members into derived class definitions.
[...]
If the using-declaration refers to a constructor of a direct base of the class being defined (e.g. using
Base::Base;
), all constructors of that base (ignoring member access) are made visible to overload resolution when initializing the derived class.If overload resolution selects an inherited constructor, it is accessible if it would be accessible when used to construct an object of the corresponding base class: the accessibility of the using-declaration that introduced it is ignored.
as such:
class B : public A {
using A::A;
};
Note the highlight that the accessibility of the using-declaration itself is ignored, meaning using A::A
in the example needn't the be placed under public
accessibility - what matters is the accessibility of the inherited constructors in B
.
Upvotes: 3
Reputation: 217235
Even add explicitly B constructor
class B : public A
{
public:
B(const std::string& s) : A(s) {}
};
or "use" the base's ones
class B : public A
{
public:
using A::A;
};
Upvotes: 0