I am new to C++ and learning the basics of this language. I read this line in a book "Instantiating a derived-class object begins a chain of constructor calls". Can someone please explain what does this statement means? There was no explaination given in the book. Please help.
It means that if you have a base class and a derived class:
struct A
{
A() { std::cout << "constructing A\n"; }
};
struct B : A
{
B() { std::cout << "constructing B\n"; }
};
then instantiating the derived class:
int main()
{
B b;
}
invokes the constructor not only for the derived class, but also for the base class:
constructing A
constructing B
and this "chain" of automatically-invoked constructors gets longer the more bases you have (i.e. the deeper your inheritance tree goes).
You can try defining an object hierarchy, and observe the effects from the execution of the constructors yourself. Here's a contrived example:
#include <iostream>
struct A
{
A(int nValue) {
std::cout << "A: " << nValue << std::endl;
}
};
struct B: public A
{
B(int nValue, double dValue)
: A(nValue) {
std::cout << "B: " << dValue << std::endl;
}
};
struct C: public B
{
C(int nValue, double dValue, char chValue)
: B(nValue, dValue) {
std::cout << "C: " << chValue << std::endl;
}
};
int main()
{
C cClass(5, 4.3, 'R');
return 0;
}
Can you imagine more complex hierarchies? What happens with other kinds of constructors? What about destructors?
A derived class is a class which inherits from another class. I suppose you're familiar with inheritance,somewhat. The derived class inherits the constructor of the base class, you just have to "override" it. So when you instantiate an object from the derived class, first the constructor of the base class is called and then the constructor of the derived class.
To instantiate something you create an instance of it:
instantiate
...
(transitive) To represent (something) by a concrete instance.
In class-based languages like C++ you have classes, which acts as blueprints, and then you have objects which are instances of specific classes.
For example, lets say you have a class A. If you then declare an object a of the class A then you instantiate an object of the class A.
Related
I struggle with the complexity of conversions and casting, and I can't find advice online that clearly guarantees efficient conversion on function return. I have two classes, Base and Derived, where Derived has no extra data members over Base. I have a named constructor for the base class that I want to return using RVO and cast to an object of the derived type with as little overhead as possible.
class Base {
public:
static Base namedConstructor(int n){
return Base(n);
}
protected:
Base(int n) : member(n){
}
int member;
};
class Derived : public Base {
static Derived nC2(int n) {
Derived derived = namedConstructor(n);
// Error: no suitable user-defined conversion from "Base" to "Derived"...
// modify derived
return derived;
}
};
Is there a way to fix the error that satisfies all the following requirements?
No use of RTTI. Dynamic casting seems unnecessary.
Only one definition of namedConstructor in case I need to modify it. If necessary, I can make it a template, but I am interested in the alternatives.
namedConstructor should take advantage of RVO in nC2.
The conversion should not silently fail if I add or remove data members from either the base or the derived class (something similar to reinterpret_cast may do this).
Add a private ctor. to Derived, which constructs it from a Base:
Derived(const Base& base) : Base(base) {
}
If later you add extra member variables to Derived, initialize them also.
This is standard-compliant (although a little bit weird), and will be optimized away in release builds.
I've added constructors and with g++ 3.0 there is copy elision:
class Base {
public:
static Base namedConstructor(int n){
return Base(n);
}
protected:
Base(int n) : member(n){
std::cout << "Create Base" << std::endl;
}
Base (const Base & b) : member (b.member) {
std::cout << "Copy Base" << std::endl;
}
int member;
};
class Derived : public Base {
public:
Derived () : Base (0) {
std::cout << "Create Derived" << std::endl;
}
Derived (const Base & b) : Base(b) {
std::cout << "Create Derived from base" << std::endl;
}
int val () { return member; }
static Derived nC2(int n) {
return namedConstructor(n); //derived;
}
};
int main ()
{
Derived d = Derived::nC2(1);
std::cout << "Value: " << d.val() << std::endl;
return 0;
}
The output from this is:
Create Base
Copy Base
Create Derived from base
Value: 1
so one Base creation, one copy of Base when creating Derived and the Derived itself.
There are no copies from namedConstructor exit or nC2, nor for the assignment in main.
I've compiled this with -O0 but with those so small functions may be there is optimization here and those are removed.
I've started learning about virtual inheritance (and how it may solve problems of having a class derived from two parent classes with same parent). To better understand the mechanism behind it, i made a following example:
class A {
public:
A(string text = "Constructor A") { cout << text << endl; }
};
class B: public A {
public:
B(): A("A called from B") { cout << "Constructor B" << endl; }
};
class C : virtual public A {
public:
C() : A("A called from C") { cout << "Constructor C" << endl; }
};
class D : public B, public C {
public:
D() { cout << "Constructor D" << endl; }
};
I have class A, class B derived from A, class C virtually derived from A, and class D derived from B and C. In main i just form an object of class D: D d; and i get the following output
Constructor A
A called from B
Constructor B
Constructor C
Constructor D
What bothers me is, why is there "Constructor A" signalizing that it is not called by either class B or C. And why is there not "A called from C" before "Constructor C". For the latter one i know it has to do with the class C being virtually derived so i guess it does not call Constructor A again since object from class A has already been formed (twice in fact).
EDIT:
In main i just make one object type D.
int main() {
D d;
}
Firstly, since B derives from A non-virtually, D ends up with two A subobjects (as if you didn't use virtual inheritance at all).
The non-virtual A is constructed by B() (hence "A called from B"), and the virtual one prints "Constructor A" when constructed.
That's because the constructors of virtual (possibly indirect) bases are always called by the constructor of the most derived class (D), rather than by the constructors of any intermediate bases (C).
It means that : A("A called from C") in C() is ignored (since you're not constructing a standalone C). And since D() doesn't mention A in its member initializer list, the virtual A is constructed without any parameters (as if by : A()).
Also, it's worth mentioning that all virtual bases are constructed before the non-virtual ones.
So your code is guaranteed to print Constructor A before A called from B.
The problem
Your code forgot something and you still have two A objects in a D object. You can verify this claim by adding a public int test member to A and try the following code. You will get two different addresses:
D d;
cout << &d.B::test <<endl; // the non virtual A subobject of B
cout << &d.C::test <<endl; // the virtual A subobject of C
Online demo
The solution
All classes that share A virtually and that directly inherit from A must declare the virtual inheritance. So you need to correct class B:
class B: virtual public A {...} // you forgot the virtual here
The code snippets above would work as expected, and you could even address d.test without getting any ambiguity error. Online demo
Edit: The delicate construction of A
The C++ rules require each object with a virtual A sub-object to provide a constructor for A. In your case, D should provide for the virual A's construction.
Since there is no explicit constructor, D will look for a default-construct A. And it finds one, since you provide a default argument for the A constructor. It's misleading because it tells you "A constructor" when in reality it was D that used it.
If you remove this default argument, your code won't compile anymore. You then need something like this to get A properly constructed:
class A {
public:
int test;
A(string text) { cout << "A is constructed: "<<text << endl; }
};
class D : public B, public C {
public:
D() : A("Mandatory, if there is no default consructor") { cout << "Constructor D" << endl; }
};
Online demo
Why are the C++ construction rules like that ? Because when you have virtual inheritance, there is no reason that the A construction by B is drawn over the construction by C . Nor the contrary. On the other side, both B and C define how to construct their A sub-object. To solve the ambiguity in the choice of the right construction, this rule was decided. And it may be painful if the virtual class doesn't have a default constructor.
When a type has a virtual base, the virtual base gets constructed from the constructor of the most-derived type. So "Constructor A" is called from D's constructor.
A bit more detail:
#include <iostream>
struct base {
base() { std::cout << "base()\n"; }
base(int) { std::cout << "base(int)\n"; }
};
struct i1 : virtual base {
i1() : base(0) { std::cout << "i1()\n"; }
};
struct i2 : virtual base {
i2() : base(1) { std::cout << "i2()\n"; }
};
struct d : i1, i2 {
};
Now, if the code creates an object of type i1 the default constructor for i1 calls base(int), as written.
But when you create an object of type d, the constructor for d is responsible for constructing the base object. Since d does not have a default constructor, the compiler generates one that calls the default constructor for base before it calls the default constructors for i1 and i2.
int main() {
d d_obj;
return 0;
}
the output here is
[temp]$ Clang++ test.cpp
[temp]$ ./a.out
base()
i1()
i2()
[temp]$
Note that the constructors for i1 and i2 did not construct the base subobject. The compiler took care fo that: the base should only be initialized once, and the constructor for d did that.
If you want a different initialization for the base object, write that in the constructor:
d::d() : base(2) {}
adding that to the class d produces this output:
[temp]$ Clang++ test.cpp
[temp]$ ./a.out
base(int)
i1()
i2()
[temp]$
Is the following approach good?
class TA { };
class TB : TA { };
std::shared_ptr<TA> spta;
spta.reset(new TB);
There's one problem with the code shown, TB must inherit publicly from TA. You have a shared_ptr<TA>, so the pointer you want to store in it must be convertible to TA, but with private inheritance, the base is inaccessible so your code will not compile.
class TA { };
class TB : public TA { };
Beyond this, the code has no errors and is well-behaved. Typically, when you perform polymorphic deletion of a derived class instance through a base class pointer, you need the base class' destructor to be virtual so the derived class destructor is called, but in case of shared_ptr this is not necessary. shared_ptr::reset is a function template that'll accept any Y* that is convertible to the managed pointer type. The same is true for shared_ptr's constructor template.
That being said, you should prefer making the base class' destructor virtual, especially if the classes involved have other virtual functions.
No, it is not for TA is private.
Moreover, as suggested in the comments, the destructor of the base class ought to be virtual. It is usually a good practice, for you cannot guarantee that instances of your classes will be used only with shared pointers.
To have it working, you must at least modify these lines:
class TA { };
class TB : TA { };
As it follows:
class TA { virtual ~TA() { } };
class TB : public TA { };
Those ones are good as the following example is good:
class TA { virtual ~TA() { } };
class TB : public TA { };
TA *spta = nullptr;
spta = new TB;
It mainly depends on what good means for you. It's legal, at least.
This is not an answer to the question, it is an attempt to clear up any confusion about shared_ptr's seemingly magical ability to avoid the use of a virtual destructor.
Here's a little demo program:
#include <iostream>
#include <memory>
struct A {
~A() { std::cout << __func__ << std::endl; }
void foo() { do_foo(); }
protected:
virtual void do_foo() {
std::cout << "A::" << __func__ << std::endl;
}
};
struct B : A {
~B() { std::cout << __func__ << std::endl; }
virtual void do_foo() override {
std::cout << "B::" << __func__ << " ";
A::do_foo();
}
};
using namespace std;
auto main() -> int
{
std::shared_ptr<A> p = std::make_shared<A>();
p->foo();
p = std::make_unique<B>();
p->foo();
cout << "deleting B:" << endl;
return 0;
}
expected output:
A::do_foo
~A
B::do_foo A::do_foo
deleting B:
~B
~A
Notice that the correct destructor was called when the B was destroyed at the end of main().
I'm attempting to call a method from a base class with the same name as a method in the derived class. Here's a simplified example:
#include <iostream>
using namespace std;
class Base
{
public:
void print() {
cout << "Printing from base" << endl;
}
void print(int num) {
cout << "Printing number from base: " << num << endl;
}
};
class Derived : public Base
{
using Base::print;
public:
void print() {
cout << "Printing from derived" << endl;
}
};
int main()
{
Derived x;
x.print();
x.Base::print(1);
//x.print(1); // Gives a compilation error
return 0;
}
Basically, I'd like to be able to call x.print(1) and get "Printing number from base: 1", that is, automatically call the method which matches the signature, even though it resides in the base class.
Without the using Base::print;, I get error: no matching function for call to 'Derived::print(int)', which makes perfect sense due to name hiding.
Thus, I added that line, but now the error is error: 'void Base::print(int)' is inaccessible
Why is this the case? I use public inheritance, so I would have thought it was readily available?
As demonstrated in the example, it works fine to manually call x.Base::print(1);, but I would like to do it more transparently. Then of course I can re-implement a wrapper to the function in the derived class, but that does not seem very elegant either.
I apologize if this has been covered in an earlier question, I read a bunch of them and found a lot of similar cases, but nothing that helped me.
The placement of the using directive decides about the visibility. Simply place it into the public area and you should be fine:
//...
class Derived : public Base
{
public:
using Base::print;
void print() {
cout << "Printing from base" << endl;
}
};
//...
http://ideone.com/06NNk
You can make your functions virtual. Any virtual functions inherited from the base class that aren't overloaded will be called through the derived class.
class base
{
public:
virtual void Foo() {}
}
class Derived
{
}
Derived d;
d.foo(); // calls base::foo()
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does an overridden function in the derived class hide other overloads of the base class?
Does f(int) in base class inherited in derived derived class D?
if yes then why overloading is not working here.
and if no then why f(int) is not inherited as class d is publicly derived.
I am confused.
class B {
public:
int f(int i) { cout << "f(int): "; return i+1; }
// ...
};
class D : public B {
public:
double f(double d) { cout << "f(double): "; return d+1.3; }
// ...
};
int main()
{
D* pd = new D;
cout << pd->f(2) << '\n';
cout << pd->f(2.3) << '\n';
}
This is the Classical example for Function Hiding.
The overload resolution in C++ does not work across classes, A function in derived class Hides all the functions with identical name in the Base class. Compiler only sees the function in derived class for an derived class object.
You can Unhide all the base class functions for your derived class by using the using Declaration. in your derive class.
Adding,
using B::f;
in your derived class will enable your derived class object to access all the functions with the name f() int the Base class as if they were overloaded functions in Derived class.
This should be a good read:
What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?
I think if you give a derived class a function with the same name as functions existing in a base class, the derived class' function will hide the base class' functions. If you merely wanted to overload, use the using keyword.
class B {
public:
int f(int i) { cout << "f(int): "; return i+1; }
// ...
};
class D : public B {
public:
using B::f; //brings in all of B's "f" functions
//making them equals of D's "f" functions.
double f(double d) { cout << "f(double): "; return d+1.3; }
// ...
};
int main()
{
D* pd = new D;
cout << pd->f(2) << '\n';
cout << pd->f(2.3) << '\n';
}