This question already has answers here:
Initialization Order of Class Data Members
(2 answers)
Closed 11 months ago.
This little test program crashes and I'm interested why it does:
#include <iostream>
struct SomeClass {
SomeClass() {
}
virtual ~SomeClass() {
}
void test() {
std::cout << "test" << std::endl;
}
virtual void onInit() {
std::cout << "test" << std::endl;
}
};
struct Base {
Base(SomeClass *ptr) {
ptr->test();
ptr->onInit();
}
};
struct Derived : Base {
SomeClass cls;
Derived() : cls(), Base(&cls) {
}
};
int main(int, const char **) {
Derived test;
}
Why can't I call the virtual function onInit from the base class? Isn't that fully initialized when I use cls() in the initializer list?
Base classes and members are initialized in the order of declaration in the class and not in the order you put in the initialization list.
Bases are always initialized before members, so the Base's constructor dereferences a pointer to an uninitialized object, which is undefined behavior.
Related
This question already has answers here:
Why does an overridden function in the derived class hide other overloads of the base class?
(4 answers)
Closed 1 year ago.
This does not compile:
struct Base
{
void something( int a ) { }
};
struct Derived : public Base
{
static void something()
{
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->something( 11 );
}
};
It’s possible to fix with using Base::something but still, is it possible to make inheritance work as advertised even inside methods?
By using the same name for the function in the derived class you hide the symbol from the base class.
You can solve it by pulling in the name from the base class with the using statement:
struct Derived : public Base
{
// Also use the symbol something from the Base class
using Base::something;
static void something()
{
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->something( 11 );
}
};
I'm not exactly sure what you are trying to accomplish. I added virtual, and changed the name of the Derived something class function, and put in two variants. One variant calls through virtual inheritance, the other calls Base class member function directly.
#include <iostream>
using std::cout;
namespace {
struct Base {
virtual ~Base();
virtual void something(int a) { std::cout << "Base a:" << a << "\n"; }
};
Base::~Base() = default;
struct Derived : Base {
void something(int b) override { std::cout << "Derived b:" << b << "\n"; }
static void action() {
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->something(11);
}
static void other_action() {
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->Base::something(11);
}
};
} // anon
int main() {
Derived::action();
Derived::other_action();
}
This question already has answers here:
What if the virtual destructor defined in derived class, but not the top of hierarchy? C++
(4 answers)
Closed 3 years ago.
I am just trying to understand some concepts of inheritance/polymorphism and tried to inherit a class from std::string as shown below:
#include <iostream>
using namespace std;
class MyClass : public std::string
{
virtual ~MyClass()
{
cout << "Inside Virutal Destructor" << endl;
}
};
int main()
{
string *s = new MyClass();
delete s;
cout << "Program started" << endl; //NEVER REACHES HERE
}
QUESTION: With the above code, I was expecting a call to the virtual destructor at the line delete s but as soon as the program reaches there, the program enters into some undefined state (i.e. doesn't crash, doesn't go forward). Where is the program stuck?
The standard class template std::basic_string does not have a virtual destructor. So the class does not have a pointer to the destructor in the table of virtual function pointers. As a result the virtual destructor of the derived class will not be called.
Consider the following demonstrative program
#include <iostream>
struct A
{
void f() const { std::cout << "A::f()\n"; }
};
struct B : A
{
virtual void f() const { std::cout << "virtual B::f()\n"; }
};
struct C : B
{
void f() const override { std::cout << "virtual C::f()\n"; }
};
int main()
{
C c;
A *ac = &c;
B *bc = &c;
ac->f();
bc->f();
return 0;
}
Its output is
A::f()
virtual C::f()
Class A has a non-virtual function f.
Class B has a virtual function f that hides the non-virtual function of the class A and does not override it.
Class C overrides the virtual function of the class B.
This question already has answers here:
Changing Function Access Mode in Derived Class
(4 answers)
Closed 3 years ago.
I've been playing around with inheritance and I've tried this code:
#include <iostream>
#include <string>
class Foo
{
public:
virtual void func() = 0;
protected:
virtual void doSum() const = 0;
};
class Bar : public Foo
{
public:
void func() {
doSum();
}
protected:
void doSum() const
{
std::cout << "hi, i'm doing something" << std::endl;
}
};
int main()
{
Foo* ptr = new Bar();
ptr->func();
return 0;
}
So I've also tried replacing the protected keyword in the class Bar with private like this :
private:
void doSum() const
{
std::cout << "hi, i'm doing something" << std::endl;
}
and the code happened to work just the same...
So my question is, is there any difference if I declare a protected method private when implementing a derived class? If so, what are they? Am I even allowed to do this?
So my question is, is there any difference if I declare a protected method private when implementing a derived class?
Yes.
If so, what are they?
That will prevent the next level of derived class from being able to call the derived class's implementation.
class Foo
{
protected:
virtual void doSum() const = 0;
};
class Bar : public Foo
{
private:
void doSum() const
{
std::cout << "hi, i'm doing something" << std::endl;
}
};
class Baz : public Bar
{
public:
void doSum() const
{
//===========================
Bar::doSum(); // NOT ALLOWED
//===========================
}
};
Am I even allowed to do this?
Yes.
So my question is, is there any difference if I declare a protected method private when implementing a derived class?
No. There is no difference. Unfortunately, C++ standard does not impose any requirement on the derived class to place the overriding virtual function within any particular accessibility scope. This means, the base class could declare a virtual method protected, and the derived class could implement the method in public/protected/private scope and the code will still be legal and will work.
This question already has answers here:
Calling virtual functions inside constructors
(15 answers)
Closed 6 years ago.
Why the following example prints "0" and what must change for it to print "1" as I expected ?
#include <iostream>
struct base {
virtual const int value() const {
return 0;
}
base() {
std::cout << value() << std::endl;
}
virtual ~base() {}
};
struct derived : public base {
virtual const int value() const {
return 1;
}
};
int main(void) {
derived example;
}
Because base is constructed first and hasn't "matured" into a derived yet. It can't call methods on an object when it can't guarantee that the object is already properly initialized.
When a derived object is being constructed, before the body of the derived class constructor is called the base class constructor must complete. Before the derived class constructor is called the dynamic type of the object under construction is a base class instance and not a derived class instance. For this reason, when you call a virtual function from a constructor, only the base class virtual function overrides can be called.
Actually, there is a way to get this behavior. "Every problem in software can be solved with a level of indirection."
/* Disclaimer: I haven't done C++ in many months now, there might be a few syntax errors here and there. */
class parent
{
public:
parent( ) { /* nothing interesting here. */ };
protected:
struct parent_virtual
{
virtual void do_something( ) { cout << "in parent."; }
};
parent( const parent_virtual& obj )
{
obj.do_something( );
}
};
class child : public parent
{
protected:
struct child_virtual : public parent_virtual
{
void do_something( ) { cout << "in child."; }
};
public:
child( ) : parent( child_virtual( ) ) { }
};
The question of how it works is a FAQ item.
Summarizing, while class T is being constructed, the dynamic type is T, which prevents virtual calls to derived class function implementations, which if permitted could execute code before the relevant class invariant had been established (a common problem in Java and C#, but C++ is safe in this respect).
The question of how to do derived class specific initialization in a base class constructor is also a FAQ item, directly following the previously mentioned one.
Summarizing, using static or dynamic polymorphism on may pass the relevant function implementations up to the base class constructor (or class).
One particular way to do that is to pass a “parts factory” object up, where this argument can be defaulted. For example, a general Button class might pass a button creation API function up to its Widget base class constructor, so that that constructor can create the correct API level object.
You should not polymorphically call the virtual methods from constructor.
Instead you can call them after construction of object.
Your code can be re written as follows
struct base {
virtual const int value() const {
return 0;
}
base() {
/* std::cout << value() << std::endl; */
}
virtual ~base() {}
};
struct derived : public base {
virtual const int value() const {
return 1;
}
};
int main(void) {
derived example;
std::cout << example.value() << std::endl;
}
The general rule is you don't call a virtual function from a constructor.
In C++, you cannot call a virtual / overriden method from a constructor.
Now, there is a good reason you can do this. As a "best practice in software", you should avoid calling additional methods from your constructor, even non virtual, as possible.
But, there is always an exception to the rule, so you may want to use a "pseudo constructor method", to emulate them:
#include <iostream>
class base {
// <constructor>
base() {
// do nothing in purpouse
}
// </constructor>
// <destructor>
~base() {
// do nothing in purpouse
}
// </destructor>
// <fake-constructor>
public virtual void create() {
// move code from static constructor to fake constructor
std::cout << value() << std::endl;
}
// </fake-constructor>
// <fake-destructor>
public virtual void destroy() {
// move code from static destructor to fake destructor
// ...
}
// </fake-destructor>
public virtual const int value() const {
return 0;
}
public virtual void DoSomething() {
// std:cout << "Hello World";
}
};
class derived : public base {
// <fake-constructor>
public override void create() {
// move code from static constructor to fake constructor
std::cout << "Im pretending to be a virtual constructor," << std::endl;
std::cout << "and can call virtual methods" << std::endl;
}
// </fake-constructor>
// <fake-destructor>
public override void destroy() {
// move code from static destructor to fake destructor
std::cout << "Im pretending to be a virtual destructor," << std::endl;
std::cout << "and can call virtual methods" << std::endl;
}
// </fake-destructor>
public virtual const int value() const {
return 1;
}
};
int main(void) {
// call fake virtual constructor in same line, after real constructor
derived* example = new example(); example->create();
// do several stuff with your objects
example->doSomething();
// call fake virtual destructor in same line, before real destructor
example->destroy(); delete example();
}
As a plus, I recommend programmers to use "struct" for only fields structures, and "class" for structures with fields, methods, constructors, ...
This question already has answers here:
Calling virtual functions inside constructors
(15 answers)
Closed 6 years ago.
Why the following example prints "0" and what must change for it to print "1" as I expected ?
#include <iostream>
struct base {
virtual const int value() const {
return 0;
}
base() {
std::cout << value() << std::endl;
}
virtual ~base() {}
};
struct derived : public base {
virtual const int value() const {
return 1;
}
};
int main(void) {
derived example;
}
Because base is constructed first and hasn't "matured" into a derived yet. It can't call methods on an object when it can't guarantee that the object is already properly initialized.
When a derived object is being constructed, before the body of the derived class constructor is called the base class constructor must complete. Before the derived class constructor is called the dynamic type of the object under construction is a base class instance and not a derived class instance. For this reason, when you call a virtual function from a constructor, only the base class virtual function overrides can be called.
Actually, there is a way to get this behavior. "Every problem in software can be solved with a level of indirection."
/* Disclaimer: I haven't done C++ in many months now, there might be a few syntax errors here and there. */
class parent
{
public:
parent( ) { /* nothing interesting here. */ };
protected:
struct parent_virtual
{
virtual void do_something( ) { cout << "in parent."; }
};
parent( const parent_virtual& obj )
{
obj.do_something( );
}
};
class child : public parent
{
protected:
struct child_virtual : public parent_virtual
{
void do_something( ) { cout << "in child."; }
};
public:
child( ) : parent( child_virtual( ) ) { }
};
The question of how it works is a FAQ item.
Summarizing, while class T is being constructed, the dynamic type is T, which prevents virtual calls to derived class function implementations, which if permitted could execute code before the relevant class invariant had been established (a common problem in Java and C#, but C++ is safe in this respect).
The question of how to do derived class specific initialization in a base class constructor is also a FAQ item, directly following the previously mentioned one.
Summarizing, using static or dynamic polymorphism on may pass the relevant function implementations up to the base class constructor (or class).
One particular way to do that is to pass a “parts factory” object up, where this argument can be defaulted. For example, a general Button class might pass a button creation API function up to its Widget base class constructor, so that that constructor can create the correct API level object.
You should not polymorphically call the virtual methods from constructor.
Instead you can call them after construction of object.
Your code can be re written as follows
struct base {
virtual const int value() const {
return 0;
}
base() {
/* std::cout << value() << std::endl; */
}
virtual ~base() {}
};
struct derived : public base {
virtual const int value() const {
return 1;
}
};
int main(void) {
derived example;
std::cout << example.value() << std::endl;
}
The general rule is you don't call a virtual function from a constructor.
In C++, you cannot call a virtual / overriden method from a constructor.
Now, there is a good reason you can do this. As a "best practice in software", you should avoid calling additional methods from your constructor, even non virtual, as possible.
But, there is always an exception to the rule, so you may want to use a "pseudo constructor method", to emulate them:
#include <iostream>
class base {
// <constructor>
base() {
// do nothing in purpouse
}
// </constructor>
// <destructor>
~base() {
// do nothing in purpouse
}
// </destructor>
// <fake-constructor>
public virtual void create() {
// move code from static constructor to fake constructor
std::cout << value() << std::endl;
}
// </fake-constructor>
// <fake-destructor>
public virtual void destroy() {
// move code from static destructor to fake destructor
// ...
}
// </fake-destructor>
public virtual const int value() const {
return 0;
}
public virtual void DoSomething() {
// std:cout << "Hello World";
}
};
class derived : public base {
// <fake-constructor>
public override void create() {
// move code from static constructor to fake constructor
std::cout << "Im pretending to be a virtual constructor," << std::endl;
std::cout << "and can call virtual methods" << std::endl;
}
// </fake-constructor>
// <fake-destructor>
public override void destroy() {
// move code from static destructor to fake destructor
std::cout << "Im pretending to be a virtual destructor," << std::endl;
std::cout << "and can call virtual methods" << std::endl;
}
// </fake-destructor>
public virtual const int value() const {
return 1;
}
};
int main(void) {
// call fake virtual constructor in same line, after real constructor
derived* example = new example(); example->create();
// do several stuff with your objects
example->doSomething();
// call fake virtual destructor in same line, before real destructor
example->destroy(); delete example();
}
As a plus, I recommend programmers to use "struct" for only fields structures, and "class" for structures with fields, methods, constructors, ...