Is there any harm in shadowing a parent constructor? It doesn't seem like anything is wrong, but my IDE is indicating and not warning me about it. Quick example
#include <iostream>
#include <string>
namespace NS1 {
class A {
public:
A(){std::cout<<"I am A\n";}
virtual ~A(){}
};
}
namespace NS2 {
class A : public NS1::A{
public:
A(): NS1::A() {}
~A(){}
};
}
int main()
{
NS2::A a;
}
It works as expected, but... is it bad to shadow?
There's nothing wrong with this code, except that it could possibly be improved by following the Rule Of Zero:
namespace NS2 {
class A : public NS1::A {
public:
// Has implicitly declared default constructor, copy constructor,
// move constructor, copy assignment, move assignment, and destructor.
};
}
In fact, the constructor NS2::A::A does not "shadow" NS1::A::A at all.
A derived class does not inherit constructors from any base class by default. If you want that, you can say that it should with a declaration like using Base::Base;.
In your example, if NS2::A did not declare its default constructor A();, it would still get one implicitly with exactly the same behavior - but this is because a class with no user-declared constructors gets an implicitly declared/defined default constructor, not because NS1::A has such a constructor. If we add A(std::string); to NS1::A, this doesn't make it valid to create NS2::A("test").
#include <iostream>
#include <string>
namespace NS1 {
class A {
public:
A(){std::cout<<"I am A\n";}
explicit A(std::string s) {
std::cout << "Creating NS1::A from string '" << s << "'\n";
}
virtual ~A(){}
};
}
namespace NS2 {
class A : public NS1::A {
};
}
int main()
{
NS2::A a; // OK
NS2::A b("test"); // Error, no matching constructor!
}
And then, if we add a similar A(std::string); to NS2::A, that's a different function. Its member initializer list will determine whether creating the NS1::A subobject uses the NS1::A::A(); default constructor, the NS1::A::A(std::string); constructor from string, or something else. But we wouldn't say that NS2::A::A(std::string); "hides" NS1::A::A(std::string); because the NS1::A constructor couldn't be used directly to initialize an NS2::A object even without the NS2::A::A(std::string); constructor present.
Your compiler/IDE probably means this:
namespace X {
struct A {
A() = default;
};
}
struct B : X::A {
B () : A() { // <- you can use just A, as opposed to X::A here
A a; // <- also here
}
};
struct A : X::A {
A () : X::A() { // <- you cannot use unqualified A here to refer to X::A,
// because it is shadowed by class's own name
X::A a; // <- neither here
}
};
There is nothing particularly harmful in it, because you can always use the qualified name. So I would say it makes no sense to warn about it, and it's a bug if the compiler does so.
Related
Suppose you wanted to reproduce the following Python snippet:
class Base:
name = "base"
def announce(self):
print(self.name)
class Derived(Base):
name = "derived"
Base().announce()
Derived().announce()
... which would output:
"base"
"derived"
Initially, you may be inclined to write something like the following:
#include <iostream>
#include <string>
struct Base {
std::string name = "base";
void announce() {
std::cout << name << std::endl;
}
};
struct Derived : public Base {
std::string name = "movie";
};
int main() {
Base().announce();
Derived().announce();
return 0;
}
But here Derived.name simply shadows Base.name. Calling Derived.announce() references Base.name and prints "base".
Is there any way to implement this behaviour? Ideally without class templates if possible.
C++ doesn't work like Python (which isn't surprising, they are two very different languages after all), and member variables defined in an inherited class really defines a new variable that is unrelated to the variables of the parent class.
One possible solution is to create a second (possibly protected) Base constructor which takes the name as an argument, and then the Derived class can use it to initialize the member:
struct Base {
Base() = default; // A defaulted default constructor
std::string name = "base";
void announce() {
std::cout << name << std::endl;
}
protected:
explicit Base(std::string name)
: name{ std::move(name) } // Initialize the member
{
}
};
struct Derived : public Base {
Derived()
: Base("movie") // Initialize the base class using the special constructor
{
}
};
The default Base default constructor is needed, because if you declare another constructor the compiler won't automatically generate a default constructor for you.
Why making a constructor explicit does not prevent it to be implicitly called by derived class?
class A{
public:
explicit A(){}
};
class B : public A{
public:
B(){ //Constructor A() is called implicitly
//...
}
}
I had a situation in my program when I'd rather have compiler error in that case, it would save me a lot of time to find a bug. For now I changed default constructor of A to accept a dummy "int" argument to achieve that, but shouldn't "explicit" keyword work for this?
g++-4.8 compiles the code above without any errors or warnings.
Your assumption is wrong on the explicit keyword.
The explicit keyword isn't meant to prevent the constructor from being called from a derived class but rather to prevent implicit conversions like the one in the sample here: https://stackoverflow.com/a/121163/1938163
I'm summarizing the relevant parts here:
class Foo
{
public:
// single parameter constructor, can be used as an implicit conversion
Foo (int foo) : m_foo (foo)
{
}
int GetFoo () { return m_foo; }
private:
int m_foo;
};
Since at most one implicit conversion can be done to resolve ambiguities, if you have a function like
void DoBar (Foo foo)
{
int i = foo.GetFoo();
}
the following is legit:
int main ()
{
DoBar (42); // Implicit conversion
}
And that's exactly where the explicit keyword comes into play: forbids the case above.
To solve your problem, in order to prevent your class from being used as a base class, just mark the constructor with final if you're using C++11 (http://en.wikipedia.org/wiki/C++11#Explicit_overrides_and_final)
explicit keyword is usually used with constructors that have one parameter. It prevents implicit construction of the object from type of the parameter to type of the class.
The example below will compile, and it usually is not what you want:
#include <iostream>
using namespace std;
struct Test
{
Test(int t) {}
};
void test_fun(Test t) {}
int main() {
test_fun(1); //implicit conversion
return 0;
}
With explicit keyword this example won't compile:
#include <iostream>
using namespace std;
struct Test
{
explicit Test(int t) {}
};
void test_fun(Test t) {}
int main() {
test_fun(1); //no implicit conversion, compiler error
return 0;
}
I wonder why people say:
"Inheriting class doesn't inherit the constructor".
If you could CAN use the parent class' constructor, and the parameterless constructor are called automatically no matter what.
Example:
#include <iostream>
using namespace std;
class A {
private :
int x;
public :
A () {
cout << "I anyway use parameter-less constructors, they are called always" << endl;
}
A (const int& x) {
this->x = x;
cout << "I can use the parent constructor" << endl;
}
};
class B : public A {
private :
int y;
public :
B() {
}
B (const int& x, const int& y) : A (x) {
this->y = y;
}
};
int main() {
B* b = new B(1,2);
B* b1 = new B();
return 0;
}
http://ideone.com/e.js/6jzkiP
So is it correct to 'say', constructors are inherited in c++ ? What is exact definition of "inherit" in programming languages ?
Thanks in advance.
I wonder why people say: "Inheriting class doesn't inherit the constructor".
Perhaps it is best to illustrate this with an example:
struct Foo
{
Foo(int, int) {}
};
struct Bar : Foo
{
};
What it means is that there is no Bar::Bar(int, int) constructor that you can call, despite the existence of a constructor with the same parameter list in the base class. So you cannot do this:
Bar b(42, 42);
In C++11, you can actually inherit constructors, but you must be explicit about it:
struct Bar : Foo
{
using Foo::Foo;
};
Now, you can say Bar b(42, 42);
What they mean is that constructor signatures are not inherited.
In your example, B does not have a constructor taking a single const int& even though its base class does. In this sense it has not "inherited" the constructor (but can still make use of it).
I think what they mean is:
struct A {
A(int, int) { }
};
struct B : public A {
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // error
}
To compare with “non-special” member functions:
struct A {
void f() { }
};
struct B : public A {
};
int main()
{
A a;
B b;
a.f(); // ok
b.f(); // ok too
}
But of course, from within B you can call accessible A constructors (as automatically generated ones do). Ditto for the destructor.
Note that in C++11 you can use the “inheriting constructors” feature:
struct A {
A(int, int) { }
};
struct B : public A {
using A::A;
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // ok now
}
A derived class can/must see base class constructors in order to invoke them, for consistency. However, their signature is not exposed in the derived class, hence, one cannot construct the class without an explicitly defined constructor, which forwards the required arguments to the base class constructor.
In C++11, one can inherit constructors: What is constructor inheritance?
Another approach to circumvent 'proxy constructors' in C++ < 11: How to define different types for the same class in C++
In your example, the default ("parameterless" as you say) constructor of B does invoke the default constructor of A, but this does not mean that B "inherited" that constructor, only that it "has access to" it. That is, A's default constructor is accessible from within B, yet it is not accessible from outside (no one can use A's default constructor from outside to construct an instance of B).
Another way to look at it is to ask, what is something frustrating about constructors and inheritance in C++? A common answer from some people (including myself) would be that there is no automatic facility which allows "pass-through" construction of base classes taking arguments from derived class constructors without explicitly declaring and defining the latter.
I am getting problems in initializing the nested class constructor.
Here is my code:
#include <iostream>
using namespace std;
class a
{
public:
class b
{
public:
b(char str[45])
{
cout<<str;
}
}title;
}document;
int main()
{
document.title("Hello World"); //Error in this line
return 0;
}
The error I get is:
fun.cpp:21:30: error: no match for call to '(a::b)'
You probably want something like:
class a
{
public:
a():title(b("")) {}
//....
};
This is because title is already a member of a, however you don't have a default constructor for it. Either write a default constructor or initialize it in the initialization list.
You have to either make your data member a pointer, or you can only call the data member's constructor from the initialiser list of the construtor of the class it is a member of (in this case, a)
This:
document.title("Hello World");
is not "initializing the nested class"; it's attempting to call operator() on the object.
The nested object is already initialised when you create document. Except that it's not, because you've provided no default constructor.
So what do you have here:
class A {
B title;
}
Without defining constructor for class A (as Luchian Grigore shown) title will be initialized as: B title();
You can work that around by:
A::A():title(B("Hello world"))
// Or by adding non parametric constructor:
class B {
B(){
}
B( const char *str){
}
}
Object title (in document) is already initialized and you cannot call constructor anymore, but you still may use syntax: document.title(...) by declaring and defining operator() but it won't be constructor anymore:
class B {
const B& operator()(const char *str){
cout << str;
return *this;
}
}
class A{
A(int a = 5){
DoSomething();
A();
}
A(){...}
}
Can the first constructor call the second one?
Not before C++11.
Extract the common functionality into a separate function instead. I usually name this function construct().
The "so-called" second call would compile, but has a different meaning in C++: it would construct a new object, a temporary, which will then be instantly deleted at the end of the statement. So, no.
A destructor, however, can be called without a problem.
Not before C++0x, no.
BUT, just out of academic interest I've come up with a really horrible way* to do it using a placement operator "new" (someone care to point out how portable this is?)
#include <new>
#include <iostream>
class A
{
public:
A(int i, int j)
: i_(i), j_(j) { }
A(int i)
{ new (this) A(i, 13); }
int i_,j_;
};
int
main() {
A a1(10,11), a2(10);
std::cout
<< a1.i_ << ", "
<< a1.j_ << std::endl
<< a2.i_ << ", "
<< a2.j_ << std::endl;
return 0;
}
*Hell no, I don't write this in the production code.
The answer is in fact "yes", but as others have suggested, it doesn't do what you want. You can of course use the constructor of a base class, either implicitly or explicitly:
struct B {
B() {}
B( int x ) {}
};
struct A : public B {
A() {} // calls B() implicitly
A( int a, int b ) : B( b ) {} // calls B(int) explicitly
};
Not directly. There are a few ways to work around this.
From the initializer list of your class' constructor, you can call a constructor on any base class, and on all member variables.
So you can usually refactor your class and split it into several smaller ones to solve the problem. The commonly executed code can be placed in a member object or perhaps a base class. Then each of the main class' constructors just have to decide which construcotr to use to initialize that member.
class B {
B() { }
B(int b) { DoSomething(); }
}
class A{
A(int a = 5) : b(a) { } // call B's constructor which does something
A() : b() {} // call B's constructor which does nothing
B b;
};
This is an old question; however,
class A{
A(int a = 5){
DoSomething();
A();
}
A(){...}
}
could be
class A{
A(int a = 5){
*this = A();
DoSomething();
}
A(){...}
}
As pointed out by Pavel Radzivilovsky in his answer, since C++ 11, it is possible. It is the same syntax as for explicitely calling the parent's class constructor from a child class. This is useful when a class needs to have multiple constructors (say, a default constructor and a constructor with attribute initialization) but some operations have to be done in all cases. This allows to avoid code repetitions.
Here is an example:
class A
{
public:
A()
{
foo();
}
A(Attribute attribute) : A()
{
this->attribute = attribute;
}
//------ some other code --------
private:
Attribute attribute;
void foo()
{...}
//------ some other code -------
};
In this simple example, I assume that the function foo() needs to be called in all cases for the object to be correctly initialized. With this syntax, if the second constructor (with attribute initialization) is called, it will first perform the operations in the default constructor before executing the instructions in the attribute-initialization constructor.
It can also be done the other way around: the default constructor can call another constructor with default parameters.
Before C++ 11, it was necessary to duplicate the common instructions of all constructors or define methods that do the actual object initialization.