C++ pure virtual function call doesn't throw run-time exception? [duplicate] - c++

This question already has answers here:
can dynamic binding happen without using pointer and using regular object in c++
(1 answer)
Where do "pure virtual function call" crashes come from?
(8 answers)
Closed 8 months ago.
It's said that in C++ constructor function, as long as the object has not finished construction, shouldn't call virtual function, or else there'll be "pure virtual function call error" thrown out. So I tried this:
#include<stdio.h>
class A{
virtual void f() = 0;
};
class A1 : public A{
public:
void f(){printf("virtual function");}
A1(){f();}
};
int main(int argc, char const *argv[]){
A1 a;
return 0;
}
compile it with g++ on windows, it works and prints
virtual function
So how to make my program throw out "pure virtual function call" exception?
Thanks!

You are not getting the "pure virtual method call" exception because A::f() is not being called.
A1's constructor is calling its own A1::f() method, which is perfectly safe to do during A1's construction.
The issue with calling a virtual method in a constructor has to do with a base class constructor calling a derived class method, which doesn't work since the derived portion of the object being constructed doesn't exist yet.
So, to get the exception you want, you need to call f() in A's constructor rather than in A1's constructor.

Related

Call pure virtual function from child constructor/destructor [duplicate]

This question already has answers here:
Calling virtual functions inside constructors
(15 answers)
Closed 1 year ago.
class A{
virtual void setEnable(bool enable) = 0;
};
class B : A{
B() {
setEnable(true);
}
~B() {
setEnable(false);
}
bool enable_ = false;
void setEnable(bool enable) override {
enable_ = enable;
}
};
Am I correct in understanding that the B :: setEnable function will be added to the vtable only after the constructor exits and this is undefined behavior?
Am I correct in understanding that the B::setEnable function will be added to the vtable only after the constructor exits and this is undefined behavior?
No. Inside the body of the A constructor, the A object is fully initialized, but the B object is not. The problem with calling a virtual function from a constructor is that it will unintuitively call the method of the same type that the constructor belongs to, without the polymorphic behavior.

C++ Call child function from parent [duplicate]

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().

C++. Calling a virtual member function in destructor [duplicate]

This question already has answers here:
Calling virtual function from destructor
(5 answers)
Closed 7 years ago.
Every class that gets extended with this calls abort in the destructor and the call stack tells me that the function that called abort was called from a unreasonable spot in the header file. The other functions get overriden and work fine though.
Renderable.h
#pragma once
class Renderable
{
public:
virtual void update(long delta) = 0;
virtual void destroy() = 0;
virtual void render() = 0;
virtual ~Renderable();
};
Renderable.cpp
#include "Renderable.h"
Renderable::~Renderable()
{
(this->*(&Renderable::destroy))(); // GLUtils::runOnUIThreadWithContext(this, &Renderable::destroy, true);
} // It says that it gets called from here.
When instantiating an object the base class gets initialized and then the subclass gets initialized. When destructing an object the subclass gets destructed and then the base class. After the subclass is destructed, its members and virtual methods are unavailable—there is no destroy() method to be invoked. I suggest you move the logic in the destroy() method to the subclass destructor.

C++ virtual function default argument value [duplicate]

This question already has answers here:
virtual function default arguments behaviour
(7 answers)
Closed 9 years ago.
the below is my test code, i think it will output "Der:12", but the result is "Der:11", any one can tell me why output this, and where is the default argument store?
#include <stdio.h>
class Base{
public:
virtual void show(int i = 11)
{
printf("Base:%d\n", i);
}
};
class Der : public Base{
public:
virtual void show(int i = 12)
{
printf("Der:%d\n", i);
}
};
int main()
{
Base *p = new Der();
p->show();
return 0;
}
Hmmm, I'm not sure it's actually valid to override a virtual function with a different default parameter, and it's certainly not sensible. But on the other hand, the compiler is doing the right thing, even if it's contrary to your expectations.
Base *p;
p->show();
What happens here is that the compiler looks into Base for a function taking no arguments. There isn't one, but it finds the one-argument function and calls show(int) with the default parameter of 11.
But the function is virtual, and so because p's dynamic type is Der, it's Der::show(int) that actually gets called -- but crucially, still with Base's default argument of 11, but the default argument is looked up statically, not using run-time dispatch.
I haven't tried it, but I'd imagine if you said
Der *p = new Der();
p->show();
you'd get 12 output instead.

Calling pure virtual function in constructor gives an error [duplicate]

This question already has answers here:
call to pure virtual function from base class constructor
(8 answers)
Closed 5 years ago.
class a //my base class
{
public:
a()
{
foo();
}
virtual void foo() = 0;
};
class b : public a
{
public:
void foo()
{
}
};
int main()
{
b obj; //ERROR: undefined reference to a::foo()
}
Why it gives me error? The pure virtual foo is defined. What do I need to change in my code to make it work? I need pure virtual method from base class be called in its constructor.
Calling virtual functions in a constructor is recognised as a bad thing to do.
During base class construction of a derived class object, the type of
the object is that of the base class. Not only do virtual functions
resolve to the base class, but the parts of the language using runtime
type information (e.g., dynamic_cast (see Item 27) and typeid) treat
the object as a base class type.
So your instantiation of b invokes the a constructor. That calls foo(), but it's the foo() on a that gets called. And that (of course) is undefined.
Quoted from a book "Let Us C++"by Yashwant Kanetkar
It is always the member function of the current class , is called.That
is , the virtual mechanism doesn't work within the constructor
So, the foo() of class a gets called.
Since it is declared pure virtual, it will report an error
foo function is called in class a's constructor, and at that time, object b has not been fully constructed yet, hence it's foo implementation is unavailable.
Quoted from "Effective C++":
Don't call virtual functions during construction or destruction,
because such calls will never go to a more derived class than that of
the currently executing constructor or destructor