This question already has answers here:
What are the rules for calling the base class constructor?
(10 answers)
Closed 1 year ago.
#include <iostream>
using namespace std;
class A{
public:
A(){
cout << "Hello World";
}
};
class B:public A{
public:
B(){
cout << "World";
}
};
int main(){
B obj1;
return 0;
}
Why does this program print Hello WorldWorld, shouldn't it print World because I have created object of class B, so why is the constructor of A being called?
Conceptually, a base class becomes an unnamed sub object in the derived class, whose members are available in the same scope without extra qualification, and must be initialized.
You cannot avoid that initialization - which means a relevant constructor will be called or if it cannot be constructed then compiler will not allow you to inherit.
What you probably mean is whether the constructor should have overridden the base version, the simple answer is it cannot. If you want that effect - which will not work in constructors in a common sense way - you need to use virtual functions and overriding.
Related
This question already has answers here:
call to pure virtual function from base class constructor
(8 answers)
Calling virtual functions inside constructors
(15 answers)
Closed 1 year ago.
I am trying to call an overriden function from the parent, and found out that it just crashes.
This is quite hard to describe, so here the minimal reproducible code:
#include <iostream>
class A
{
public:
A()
{
init1();
}
void init1()
{
printf("1");
init2();
printf("2");
}
virtual void init2() = 0;
};
class B : public A
{
public:
B()
: A()
{}
void init2() override
{
printf("hello");
}
};
int main()
{
B b;
return 0;
}
On MSVC 2019 it crashes, on http://cpp.sh/ it outputs "1" and then main() returns 0, but we never see "hello" or "2".
Why does it crash? What happens from a low level point of view? Is A trying to call its own init2()?
Is there a way of doing it, so I don't have to, in every derived class, add init2() in its constructor?
You can't call a derived class's overriden methods from within a base class constructor (or destructor). The derived class portion of the object doesn't exist yet.
So, to answer your questions:
yes A::A() is trying to call A::init2(), not B::init2(), and thus crashes from calling a pure virtual method.
There are ways (like via CRTP) for a base class constructor to call a derived class method, but doing so has limitations to it (ie, not being able to access any derived class data members since they still don't exist yet, only base class data members can be accessed). In your example, B::init2() doesn't access anyB data members, so it is possible for A::A() to call B::init2(), but in general you really need to wait for B to begin/finish constructing itself before you can safely call B::init2().
This question already has answers here:
C++ class member with constructor
(4 answers)
Avoid default constructor for member variable
(2 answers)
Explicitly initialize member which does not have a default constructor
(4 answers)
Closed 2 years ago.
I wish to have an object of one class contained inside a different class.
class A contained inside class B as in the simple example below.
The problem is that class A only has a parametrized constructor.
Is there another way to do declare the class A object in class B without having to use a pointer to class A ?
class A
{
public:
A(int var1, int var2);
private:
//...
};
class B
{
public:
B();
private:
A a; // Compiler error
A* a_ptr; // This will of course work fine. We can create a new A object with parameters any time using the a_ptr
};
A a; // Compiler error
except if the constructor of B explicitly calls the constructor of A with required arguments (e.g. B() : a(an_int, an_int) {...}), that requests a constructor without parameter or where all parameters have default value, but you do not have that constructor, only a constructor requiring 2 int
Is there another way to do declare the class A object in class B without having to use a pointer to class A ?
you do not declare but define / instantiate a new instance of A each time you instantiate a new instance of B
Note you can create later the instance of A without using a pointer as with a_ptr having for instance
std::vector<A> a;
and when you know the instance of A you need doing for instance
a.push_back(A(an-int, an-int));
but the fact you want only one instance is not visible in the definition of a (out of a welcome comment)
This question already has answers here:
My attempt at value initialization is interpreted as a function declaration, and why doesn't A a(()); solve it?
(5 answers)
Closed 5 years ago.
#include <iostream>
using namespace std;
class A{
public:
A(){
cout << "Class A!";}
};
int main()
{
A a();
}
the above code does not call the constructor A :: A() even though they have the same input parameters (none). however if, in the main function, I remove the parenthesis from
A a();
it calls the constructor.
so what is the difference between A a; and A a();
i believe the question here is very similar maybe even the same however if some could explain in simpler terms I would be very grateful.
Do the parentheses after the type name make a difference with new?
would declaring A a(); ever call a constructor, under any circumstances?
do parameterless constructors exist in c++, or is that the same as a default constructor?
With
A a();
you declare a as a function taking no arguments and returning an A object.
This question already has answers here:
In C++ Inheritance, Derived class destructor not called when pointer object to base class is pointed to derived class
(2 answers)
Closed 6 years ago.
I'm writing an operating system in C++. I do not have the std libs at my disposal (so I'm not sure if this works normally with std libs). It appears that if I delete an object, it only calls the destructor of the variable type (and it's parents).
For example:
Aa* aa = new Bb();
delete aa;
will only print "destructing Aa". Whereas
Bb* bb = new Bb();
delete bb;
will print both "destructing Bb" and "destructing Aa".
I tried to work around this issue by calling the sub class destructor in the super class destructor (as seen below).
Is there something I'm missing here, or will I have to resort to casting to the concrete type before the initial delete?
class Aa {
public:
~Aa();
};
class Bb : public Aa {
public:
~Bb() {
log("destructing Bb");
}
};
Aa::~Aa() {
log("destructing Aa");
// TODO checks if we are of type Bb
// ((Bb*) this)->~Bb(); // uncomment to test calling sub class destructor
}
You should make the destructor of Aa virtual:
class Aa {
public:
virtual ~Aa();
};
This is a basic concept of c++. You can read on it here (and in many other places).
Your "Aa" destructor is not virtual, so what you are observing is the expected behaviour.
To get the behaviour you expect, declare the destructor as virtual ~Aa() = default; .
This question already has answers here:
Why is there no call to the constructor? [duplicate]
(3 answers)
Most vexing parse
(1 answer)
Closed 9 years ago.
#include <iostream>
class Base
{
public:
int id;
};
int main()
{
Base b();
b.id = 1;
}
What is wrong with the object creation in the code above? What is the difference between Base b() and Base b?
This
Base b();
is parsed as a function declaration of a function called b() that returns a Base object. You need this:
Base b;
This will instantiate a Base object and call its default constructor. Note that this will not zero initialize base::id. You can fix this by providing a default constructor that does that:
class Base
{
public:
Base() : id(0) {}
int id;
};
and instantiate in the same way:
Base b;
The problem is that you are not instantiating an object, but rather declaring a function. This:
Base b(); // Function declaration! (not what you want)
Declares a function b() that returns an object of type Base and accepts no argument. Therefore, when you later try to access the member id, the compiler emits an error, because functions do not have members:
b.id = 1; // ERROR! b is a function, accessing member "id" makes no sense
If you want to create an instance of Base, instead, just remove the parentheses:
Base b; // Object instantiation! (what you want)
Notice that in C++11 you can use the uniform initialization syntax to create an instance of a class pretty much the way you were trying to do, but with curly braces instead of parentheses:
Base b{}; // Object instantiation! (what you want, in C++11)