Pointing to base, converted to Derived Pointer - c++

Is it possible to get a base's derived class's type name by using typeid( TYPE ).name() ?
Example of pushing a base pointer back into a derived pointer, statically.
#include <iostream>
#include <typeinfo>
class base
{
public:
virtual void known() = 0;
};
class derived: public base
{
public:
void known() { std::cout << " I guess this means "; }
void unknown(){ known(); std::cout << " its possible "; }
};
int main()
{
derived d;
std::cout << typeid( d ).name() << std::endl;
// Prints out being a pointer to a derived class
base* b = &d;
std::cout << typeid( b ).name() << std::endl;
// Prints out being a pointer to a base class
// But how would you use it, or in any other way,
//get the original derived type name
derived * db = (derived*) b;
// db is casted at at compile time, the derived class is known
db->unknown();
}

Given an expression whose type is a polymorphic base class, The result of the typeid operator refers to a std::type_info object representing the type of the most derived object.
Example:
#include <iostream>
#include <typeinfo>
class Base {
public:
virtual ~Base() {}
}; // Base
class Derived : public Base {};
int main() {
Derived derived;
/* By reference. */ {
Base &base = derived;
std::cout << typeid(base).name() << std::endl;
}
/* By pointer. */ {
Base *base = &derived;
std::cout << typeid(*base).name() << std::endl;
// NOTE: typeid(base).name() results in printing of the Base class' name.
}
}
Both cases above print the Derived class' name.
References
N3797: 5.2.8 Type identification.
cppreference: 2) a)

Related

Store object as it's base VIRTUAL class

Why can't one store an object as it's base virtual class ?
Consider the following example : It will segfault if Derived inherits virtually of Base
#include <iostream>
#include <memory>
class Base
{
public:
virtual ~Base() = default;
int baseInt = 42;
};
class Derived : public /* virtual */ Base // <<< Uncomment the virtual to get a segfault
{
public:
int derivedInt = 84;
};
int main()
{
Base *base_ptr = new Derived();
Derived *derived_ptr = reinterpret_cast<Derived *>(base_ptr);
std::cout << " baseInt is " << derived_ptr->baseInt
<< ", derivedInt is " << derived_ptr->derivedInt << std::endl; // segv on this line
}
The reinterpret_cast you used simply uses the Base pointer as if it were a Derived pointer.
Instead, this is one of the few situations where you should use a dynamic_cast.
The example in the documentation for dynamic_cast shows such a downcast.

Convert upcast pointer to base object that calls derived virtual [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 3 years ago.
I have two classes, one derived from the other. I want a function that returns an object (not pointer or reference) of the base class that calls the derived virtual function.
#include <iostream>
using namespace std;
class Base
{
public:
virtual void print() { cout << "Base" << endl; }
};
class Derived : public Base
{
public:
void print() { cout << "Derived" << endl; }
};
Base go()
{
Derived *derived = new Derived();
Base *base = derived;
base->print();
// (*base).print(); // prints "Derived" !
// Base base2 = (*base);
// base2.print(); // prints "Base" !
return *base;
}
int main()
{
Base base = go();
base.print();
return 0;
}
This prints out
Derived
Base
So in the go() function I managed to convert to Base and the print works. But when I return the object the print is using the base function!
I know this can work if you return a pointer or a reference but I really need to return an object. Is this possible? Why does my code not work?
As you can see, I've commented out code in go() that de-references the upcast pointer. Strangely, it prints correctly! And if I do a conversion to an object, it doesn't!
Any insight into why this is all happening would be very much appreciated.
When you return an actual object (and not a refernce or a pointer) it calls its copy ctor. In this case you return a Base class, so it calls its copy constructor and creates a new Base class object.
#include <iostream>
using namespace std;
class Base
{
public:
Base() = default;
Base(const Base & base) { std::cout << "COPY BASE" << std::endl; }
virtual void print() { cout << "Base" << endl; }
};
class Derived : public Base
{
public:
Derived() = default;
Derived(const Derived & derived) { std::cout << "COPY DERIVED" << std::endl; }
void print() { cout << "Derived" << endl; }
};
Base go()
{
Derived *derived = new Derived();
Base *base = derived;
base->print();
// (*base).print(); // prints "Derived" !
// Base base2 = (*base);
// base2.print(); // prints "Base" !
return *base;
}
int main()
{
Base base = go();
base.print();
return 0;
}
In this case the output will be:
Derived,
COPY BASE,
Base
By returning the base object itself, you're dropping any reference to it having started off as derived and subsequently upcasted (and copied).
So effectively, what you're after will not work.
If you really "need this to return an object", I recommend a thin wrapper
struct karls_return_object {
// ... stuff ...
Base *b;
};

C++ virtual function: Base class function is called instead of derived

I have following code snippet:
class base
{
public:
virtual void print(char a){ std::cout << " Base\n"; }
};
class derived : public base
{
public:
void print(float a) { std::cout << " Derived\n"; }
};
int main() {
base* d = new derived;
d->print(1.5);
}
Output is Base.
Why is the output coming from the base function and not from the derived one?
You have not overridden the function in the base class, you have overloaded it: The version in the derived class takes a float as an argument, and is quite a different beast from the base class method which takes a char. Moreover, the float version in the derived class shadows the base class version: The base class version becomes inaccessible for calls on the derived type.
As such, the following code
Derived d;
d.print('a');
d.print(1.5);
will print
Derived
Derived
because the call is resolved by the compiler to the only version of print() that's available in Derived.
Likewise, when you call d->print(1.5) through a pointer to Base, the derived class' version is inaccessible to the call: The compiler looks at the base class, sees that there is no print() method defined with a float argument, and converts the argument to char instead. It then calls the only implementation of print(char), which happens to be supplied by the base class.
If you simply change the signature of the print() method in the derived class to match that of the base class, the odd behavior will go away.
When you declare Base* d = new Derived;, the type of the class is Base, as printed by typeid(d).name(), so this instance doesn't have access to child class methods. If you change the type to Derived, you'll call the child method:
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(float a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Derived* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P7Derived
Derived
Furthermore, declaring the parent class print method virtual doesn't allow an instance of Base to call the child version of print because the child hasn't overridden it (different headers). Creating an instance of Base with Base *d = new Derived; and changing the Derived print method header to void print(char a) in the Derived class would allow you to call the child print method and output Derived, even from an instance of Base, using the virtual keyword.
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(char a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Base* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P4Base
Derived

Initialize an object with a different class

I saw this example:
http://www.cplusplus.com/doc/tutorial/typecasting/#dynamic_cast
(...)
class Base { virtual void dummy() {} };
class Derived: public Base { int a; };
(...)
Base * pba = new Derived;
Base * pbb = new Base;
(...)
Why 'pba' is a Base object if it's being initialized with Derived? Why not make it a Derived object?
Derived * pba = new Derived; // use this instead
And is it just a C++ thing?
neither pba nor pbb is an object but they are pointers of type base class Base so in your code you used he pointers polymorphically which means a base pointer can point to the same class or to its derived class object.
the object is created with new not pbb or pba themselves, consider this example:
#include <string>
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Print() const { cout << "Base print()" << endl;} // virtual function
void Greet()const {cout << "in Base Say: hello!" << endl;}
};
class Derived : public Base
{
public:
void Print() const { cout << "Derived print()" << endl;} // ovrode the base member pritn()
void Greet()const {cout << "in Derived Say: hello!" << endl;}
};
int main()
{
Base* pba = new Derived;
pba->Print(); // Derived print()
pba->Greet(); // in Base Say: hello! ??? because Greet() is not virtual
Base* pbb = new Base;
pbb->Print(); // Base print()
pbb->Greet(); // in Base Say: hello!
return 0;
}
so at runtime the pointer pba and pbb can be assigned an object of Base or Derived classes thus the virtual member function are called accordingly.

Base class destructor is not virtual and child class destructor is virtual, program crash

Why does the following program crash? I have a base class whose destructor is not virtual but the child class destructor is virtual:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base::Base CTOR " << std::endl;
}
~Base() {
std::cout << "Base::Base DTOR " << std::endl;
}
};
class Child : public Base {
public:
Child(){
std::cout << "Child::Child CTOR " << std::endl;
}
virtual ~Child() {
std::cout << "Child::Child DTOR " << std::endl;
}
};
int main (int argc, char **argv) {
Base *ptr = new Child;
delete ptr;
}
What you are observing is called "undefined behavior". Make Base's dtor virtual if you want do call delete on Child instance through Base pointer.
From the 2003 standard, 5.3.5/3:
In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a
base class of the operand’s dynamic type and the static type shall
have a virtual destructor or the behavior is undefined.
You have undefined behavior because the static type of the pointer operand to delete does not match the dynamic type of the object that it points to and you don't meet the requirements for the exception to this rule that allows passing a pointer to a base class to the object being deleted because this exception requires the base class to have a virtual destructor.
Any behaviour is possible including the code working "as expected" or a crash.
Hope this example helps you get the point:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base::Base CTOR " << std::endl;
}
~Base() {
std::cout << "Base::Base DTOR " << std::endl;
}
private:
protected:
};
class Child : public Base {
public:
Child(){
std::cout << "Child::Child CTOR " << std::endl;
}
~Child(){
std::cout << "Child::Child DTOR " << std::endl;
}
private:
protected:
};
class gChild : public Child {
public:
gChild(){
std::cout << "Child::Child gCTOR " << std::endl;
}
~gChild(){
std::cout << "Child::Child gDTOR " << std::endl;
}
private:
protected:
};
int main ( int argc, char **argv) {
Base *ptr = new gChild;
delete ptr;
}
if virtual ~Base() ,then all destructors' print gets printed.
if virtual ~child() or virtual ~gChild(),only base destructor gets printed.
It's because the destructors executes in opposite direction.and here behaviour is undefined.You must define the base destructor virtual to get the expected result.
Thanks.
Just look at this:
#include <iostream>
class Base
{
public:
void nonvirtualmethod()
{ std::cout << "Base nonvirtualmethod" << std::endl; }
virtual void virtualmethod()
{ std::cout << "Base virtualmethod" << std::endl; }
};
class Derived: public Base
{
public:
void nonvirtualmethod()
{ std::cout << "Derived nonvirtualmethod" << std::endl; }
virtual void virtualmethod()
{ std::cout << "Derived virtualmethod" << std::endl; }
};
int main()
{
Derived d;
Derived* pd = &d;
Base* pb = &d; //< NOTE: both pd and pb point to the same object
pd->nonvirtualmethod();
pb->nonvirtualmethod();
pd->virtualmethod();
pb->virtualmethod();
}
I gives you the following output:
Derived nonvirtualmethod
Base nonvirtualmethod
Derived virtualmethod
Derived virtualmethod //< invoked by a Base*
This is because there is a difference between the static type of the pb pointer (Base*)
and the dynamic type it points to (Derived).
The difference between virtual and plain methods is that non-virtual methods follow the the static type mapping (so a Base pointer invokes Base::methods), while virtual methods follow the chain of the runtime types, hence if a Base* points to a Derived, the Derived method will be called.
Destructors, in this sense, are nothing special: if it is not virtual, a Base pointer will not invoke the Derived one, hence you are left with an half-destroyed object, that is given back to the memory store.
The reason why this is UB (and not simply denied), is because the "memory store" is not managed by the language itself, but from the platform the program is hosted in: the crash most likely depends on the fact that the missing of the Derived part (still alive) will result in the operating system trying free a block of memory with a wrong starting address.