you have to use the concept of base, derive class and use them properly. while doing it, I'm faced with some problems.
Can you help me solve the issues ?
My Code :
#include <iostream>
class Base {
public:
Base (int data) : _data(data){}
virtual void printData(){
std::cout << "Base" << _data << std::endl;
}
private:
int _data;
};
class Derived : public Base {
public:
Derived(derivdata) : Base(derivdata){}
void printData(){
cout << "Derived " << _data << endl;
}
}
int main(){
Derived *var = new Derived(5);
var-> printData();
Base* basevar = static_cast<Base>(*var);
basevar-> printData();
}
Base* basevar = static_cast<Base>(*var); is wrong,
it would be Base* basevar = static_cast<Base*>(var);
but Base* basevar = var; is sufficient.
and version without memory leak:
int main(){
Derived derived(5);
derived.printData(); // "Derived 5\n"
Base& base = *derived;
base.printData(); // "Derived 5\n" as method is virtual
}
There are several problems here, that could be typos:
a missing semicolon after the class Derived
in the constructor Derived(derivdata) : Base(derivdata){} the type of derivdata is missing. (there is no default int in c++)
you are missing the namespace std:: before cout and endl in Derived::printData
in Derived::printData the member _data is not accessible, because it is private to Base (You could make it protected or write a getter for it)
The core problem is this cast: Base* basevar = static_cast<Base>(*var); This will actually dereference the value of var, then try to cast this value to Base, and afterwards tries to assign the result (of type Base) to a variable of type Base*.
For polymorphic casting you can use dynamic_cast: Base* basevar = dynamic_cast<Base*>(var);
But don't expect basevar->printData(); to print "Base", since the pointer is still pointing to an instance of Derived and the method is declared virtual.
To access a method of the base class you need to explicitly tell the compiler to do so:
basevar->Base::printData();(prints "Base5")
Related
In the following code, the function foo is copy constructing a Base object c from a Derived object d. My question is: are we getting an exact copy? Because I'm not getting the polymorphic behavior I'm expecting
#include<iostream>
class Base
{
public:
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = new Base(*d);
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Base
}
There is no virtual constructor nor copy constructor.
However, it is possible to define a function that behaves like one.
In my case, it is the virtual member function copy() which I added to OP's sample:
#include <iostream>
class Base
{
public:
virtual Base* copy() const { return new Base(*this); }
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
virtual Base* copy() const override { return new Derived(*this); }
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = d->copy();
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Derived
return 0;
}
Output:
Hello Derived
Live Demo on coliru
The drawback is that every derived class of Base has to provide it to make it function properly. (I've no idea how to convince the compiler to check this for me with any trick.)
A partial solution could be to make copy() pure virtual in the class Base (assuming it is not meant to be instantiable).
you may wonna change the line of new
Base* c = new Derived(*d);
so you have the type Derived in a Base pointer. During runtime it is looked up, which type it is and you get the right output.
let me know if im wrong... just created this out of my mind on the fly.
To answer your question about whether or not this is copy constructing lets add some members. Base will have a member, m_b and Derived will inherit m_b but also have another member m_d
#include <iostream>
struct Base {
const int m_b;
Base() = delete;
Base(const int a_b) : m_b(a_b) {}
virtual void sayHello() {
std::cout << "Base " << m_b << std::endl;
}
};
struct Derived : public Base {
const int m_d;
Derived() = delete;
Derived(const int a_b, const int a_d) : Base(a_b), m_d(a_d) {}
void sayHello() override {
std::cout << "Derived " << m_b << ' ' << m_d << std::endl;
}
};
void foo(Derived* a) {
Base* b = new Base(*a);
b->sayHello(); // Output is "Base 1", 1 was copied from argument a
}
void bar(Derived* a) {
Base* d = new Derived(*a);
d->sayHello(); // Output is "Derived 1 2"
}
int main() {
Derived d(1, 2);
foo(&d);
bar(&d);
return 0;
}
The line:
Base* b = new Base(*a);
Created a Base and so sayHello calls Base's implementation which doesn't know about m_d. However this line does copy m_b from the derived class
The line:
Base* d = new Derived(*a);
Created a Derived and so sayHello calls Derived's implementation which copied both m_b and m_d
Expected polymorphic behavior will come into existence when the Base class pointer points to Derived class object. Then at run time the actual type of object pointed to by the Base class pointer will be checked and appropriate function will get called.
Base* c = new Base(*d); // <<-- case of object slicing
Here, c points to Base class object. Therefore, c->sayHello() ; is bound to call the Base::sayHello() at runtime.
are we getting an exact copy?. No since you are creating a Base object due to new Base. Due to object slicing the Base part of the *d object is passed to copy c'tor and what you get is corresponding Base object.
Base *c = new Derived(*d); will give the expected behavior.
How can i get my Base pointer to instantiate a derived object and use its functions? Is there a way to type cast this like java?
Consider this sample code:
int main(){
cBase *pBase = 0;
if (1 < 2)
{
pBase = new cDerived;
}
}
class cBase
{public:
virtual void printMe()
{
std::cout << "printed cBase" << endl;
}
};
class cDerived: public cBase
{public:
virtual void printMe()
{
std:: cout << "printed cDerived" << endl;
}
};
However when i do this; it gives me an error "Expression must have class type".
cBase *pBase = 0;
if (1 < 2)
{
pBase = new cDerived;
pBase.printMe();
}
Fix it like this
#include <iostream>
using namespace std;
class cBase
{
public:
virtual ~cBase() {};
virtual void printMe()
{
std::cout << "printed cBase" << endl;
}
};
class cDerived: public cBase
{public:
virtual void printMe()
{
std:: cout << "printed cDerived" << endl;
}
};
int main(){
cBase *pBase = 0;
if (1 < 2)
{
pBase = new cDerived;
pBase->printMe();
delete pBase;
}
}
Steps to fix.
Move main function after declaration of cBase and cDerived classes or forward declare those classes before main.
Change pBase.printMe() to pBase->printMe(). Since pBase is a pointer you must dereference it before accessing its members. pBase->printMe() is like shorthand for (*pBase).printMe()
Plus a few other bits of housekeeping. Delete the pBase object and since you are deleting a derived class (cDerived) using a pointer to a base class (cBase) you must declare the base classes destructor virtual, or the cBase destructor will be called when pBase is deleted when you really wanted the cDerived destructor to be called here.
In C++, in order to get to the method/field of a pointer to a class/structure, you have to use the -> operator.
I have the following code:
main.hxx:
#include <iostream>
class Base{
public:
Base() {}
~Base() {}
virtual void whoAreYou() { std::cout << "I am base!" << std::endl;}
};
class Sub : public Base{
public:
Sub() {}
~Sub() {}
virtual void whoAreYou() { std::cout << "I am Sub!" << std::endl;}
};
class Factory {
public:
static Base getBase() { return Base(); }
static Base* getBasePtr() { return new Base(); }
static Base getSub() { return Sub(); }
static Base* getSubPtr() { return new Sub(); }
};
main.cxx
#include "main.hxx"
int main (int argc, char **argv) {
// Non pointers
Factory::getBase().whoAreYou();
Factory::getSub().whoAreYou();
// Pointers
Base* basePtr = Factory::getBasePtr();
Base* subPtr = Factory::getSubPtr();
basePtr->whoAreYou();
subPtr->whoAreYou();
delete basePtr, subPtr;
return 0;
}
When run, it prints the following:
I am base!
I am base!
I am base!
I am Sub!
I was expecting "Factory::getSub().whoAreYou();" to print "I am Sub!". Is it because when not using a pointer it gets casted to a Base?
I was expecting Factory::getSub().whoAreYou(); to print "I am Sub!".
No, the function returns a Base, so a Base is what you get.
Is it because when not using a pointer it gets casted to a Base?
Yes (although the word is "converted" not "casted" - a cast is an explicit conversion, and this conversion is implicit). This is sometimes called "slicing", since the derived-class part of the object is "sliced off" when it's copied.
Also, beware that the following:
delete basePtr, subPtr;
only deletes subPtr. You need a separate delete expression for each. You also need a virtual destructor in Base to safely delete subPtr.
This line creates a Sub then call Base default copy constructor to create a instance of Base from a the instance Sub:
static Base getSub() { return Sub(); }
Hence your log.
More generaly a Base is a Base instance, whereas Base* is a pointer on a Base instance or an object that inherits Base.
I've been confused by the converting a pointer to base class object into pointer of derivate class.
Please check the following code:
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
The result is:
I'm a virtual function in base.
I'm a function in derivate class.
Can anyone help me explain why d1->print() print "I'm a virtual function in base."?
#include <iostream>
using namespace std;
class base
{
public:
virtual void print()
{
cout << "I'm a virtual function in base." << endl;
}
};
class derivate_class : public base
{
public:
void print()
{
cout << "I rewrite the virtual function in base." << endl;
}
void print1()
{
cout << "I'm a function in derivate class." << endl;
}
};
int main()
{
base* b = new base();
derivate_class *d = new derivate_class();
b->print();
d->print1();
base* cb = b;
b = d;
b->print();
cout << "*********************" << endl;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
system("pause");
return 0;
}
It's UB, so anything can happen.
But here's an explanation: d1 doesn't actually point to a derivate_class, but to a base.
base* b = new base();
//...
base* cb = b;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
The call is resolved dynamically because it's through a pointer and the method is virtual.
print1 isn't virtual so the call is resolved statically. print however is virtual, so the implementation in the most derived type is called. But the most derived type is actually base in this case.
Under the hood, the method print is looked for in the virtual function table that the vfptr in cb points to. Since cv is a base, the table will be that of base, which contains the function print with the base::print implementation. That's why that's the function getting called.
d1 is a derivate_class pointer but the data it's actually pointing to (cb) is of type base. Since print() is virtual, the call is resolved dynamically and so it will find base's implementation in the virtual function table instead of derivate_class's.
In C++, is there any way to query the type of an object and then use that information to dynamically create a new object of the same type?
For example, say I have a simple 3 class hierarchy:
class Base
class Foo : public Base
class Bar : public Base
Now suppose I give you an object cast as type Base -- which is in reality of type Foo.
Is there a way to query the type and use that info to later create new objects of type Foo?
Clone method
There is nothing provided by the language that queries type and lets you construct from that information, but you can provide the capability for your class hierarchy in various ways, the easiest of which is to use a virtual method:
struct Base {
virtual ~Base();
virtual std::auto_ptr<Base> clone(/*desired parameters, if any*/) const = 0;
};
This does something slightly different: clone the current object. This is often what you want, and allows you to keep objects around as templates, which you then clone and modify as desired.
Expanding on Tronic, you can even generate the clone function.
Why auto_ptr? So you can use new to allocate the object, make the transfer of ownership explicit, and the caller has no doubt that delete must deallocate it. For example:
Base& obj = *ptr_to_some_derived;
{ // since you can get a raw pointer, you have not committed to anything
// except that you might have to type ".release()"
Base* must_free_me = obj.clone().release();
delete must_free_me;
}
{ // smart pointer types can automatically work with auto_ptr
// (of course not all do, you can still use release() for them)
boost::shared_ptr<Base> p1 (obj.clone());
auto_ptr<Base> p2 (obj.clone());
other_smart_ptr<Base> p3 (obj.clone().release());
}
{ // automatically clean up temporary clones
// not needed often, but impossible without returning a smart pointer
obj.clone()->do_something();
}
Object factory
If you'd prefer to do exactly as you asked and get a factory that can be used independently of instances:
struct Factory {}; // give this type an ability to make your objects
struct Base {
virtual ~Base();
virtual Factory get_factory() const = 0; // implement in each derived class
// to return a factory that can make the derived class
// you may want to use a return type of std::auto_ptr<Factory> too, and
// then use Factory as a base class
};
Much of the same logic and functionality can be used as for a clone method, as get_factory fulfills half of the same role, and the return type (and its meaning) is the only difference.
I've also covered factories a couple times already. You could adapt my SimpleFactory class so your factory object (returned by get_factory) held a reference to a global factory plus the parameters to pass to create (e.g. the class's registered name—consider how to apply boost::function and boost::bind to make this easy to use).
The commonly used way to create copies of objects by base class is adding a clone method, which is essentially a polymorphic copy constructor. This virtual function normally needs to be defined in every derived class, but you can avoid some copy&paste by using the Curiously Recurring Template Pattern:
// Base class has a pure virtual function for cloning
class Shape {
public:
virtual ~Shape() {} // Polymorphic destructor to allow deletion via Shape*
virtual Shape* clone() const = 0; // Polymorphic copy constructor
};
// This CRTP class implements clone() for Derived
template <typename Derived> class Shape_CRTP: public Shape {
public:
Shape* clone() const {
return new Derived(dynamic_cast<Derived const&>(*this));
}
};
// Every derived class inherits from Shape_CRTP instead of Shape
// Note: clone() needs not to be defined in each
class Square: public Shape_CRTP<Square> {};
class Circle: public Shape_CRTP<Circle> {};
// Now you can clone shapes:
int main() {
Shape* s = new Square();
Shape* s2 = s->clone();
delete s2;
delete s;
}
Notice that you can use the same CRTP class for any functionality that would be the same in every derived class but that requires knowledge of the derived type. There are many other uses for this besides clone(), e.g. double dispatch.
There's only some hacky ways to do this.
The first and IMHO the ugliest is:
Base * newObjectOfSameType( Base * b )
{
if( dynamic_cast<Foo*>( b ) ) return new Foo;
if( dynamic_cast<Bar*>( b ) ) return new Bar;
}
Note that this will only work if you have RTTI enabled and Base contains some virtual function.
The second an neater version is to add a pure virtual clone function to the base class
struct Base { virtual Base* clone() const=0; }
struct Foo : public Base { Foo* clone() const { return new Foo(*this); }
struct Bar : public Base { Bar* clone() const { return new Bar(*this); }
Base * newObjectOfSameType( Base * b )
{
return b->clone();
}
This is much neater.
One cool/interesting thing about this is that
Foo::clone returns a Foo*, while Bar::clone returns a Bar*. You might expect this to break things, but everything works due to a feature of C++ called covariant return types.
Unfortunately covariant return types don't work for smart pointers, so using sharted_ptrs your code would look like this.
struct Base { virtual shared_ptr<Base> clone() const=0; }
struct Foo : public Base { shared_ptr<Base> clone() const { return shared_ptr<Base>(new Foo(*this) ); }
struct Bar : public Base { shared_ptr<Base> clone() const { return shared_ptr<Base>(new Bar(*this)); }
shared_ptr<Base> newObjectOfSameType( shared_ptr<Base> b )
{
return b->clone();
}
You can use e.g. typeid to query an object's dynamic type, but I don't know of a way to directly instantiate a new object from the type information.
However, apart from the clone approach mentioned above, you could use a factory:
#include <typeinfo>
#include <iostream>
class Base
{
public:
virtual void foo() const
{
std::cout << "Base object instantiated." << std::endl;
}
};
class Derived : public Base
{
public:
virtual void foo() const
{
std::cout << "Derived object instantiated." << std::endl;
}
};
class Factory
{
public:
static Base* createFrom( const Base* x )
{
if ( typeid(*x) == typeid(Base) )
{
return new Base;
}
else if ( typeid(*x) == typeid(Derived) )
{
return new Derived;
}
else
{
return 0;
}
}
};
int main( int argc, char* argv[] )
{
Base* X = new Derived;
if ( X != 0 )
{
std::cout << "X says: " << std::endl;
X->foo();
}
Base* Y = Factory::createFrom( X );
if ( Y != 0 )
{
std::cout << "Y says: " << std::endl;
Y->foo();
}
return 0;
}
P.S.: The essential part of this code example is of course the Factory::createFrom method. (It's probably not the most beautiful C++ code, since my C++ has gone a little rusty. The factory method probably shouldn't be static, on second thought.)
I used macros in my project to synthesize such methods.
I'm just researching this approach now, so I may be wrong, but here's an answer to your question in my code of IAllocable.hh. Note that I use GCC 4.8, but I hope 4.7 suits.
#define SYNTHESIZE_I_ALLOCABLE \
public: \
auto alloc() -> __typeof__(this) { return new (__typeof__(*this))(); } \
IAllocable * __IAllocable_alloc() { return new (__typeof__(*this))(); } \
private:
class IAllocable {
public:
IAllocable * alloc() {
return __IAllocable_alloc();
}
protected:
virtual IAllocable * __IAllocable_alloc() = 0;
};
Usage:
class Usage : public virtual IAllocable {
SYNTHESIZE_I_ALLOCABLE
public:
void print() {
printf("Hello, world!\n");
}
};
int main() {
{
Usage *a = new Usage;
Usage *b = a->alloc();
b->print();
delete a;
delete b;
}
{
IAllocable *a = new Usage;
Usage *b = dynamic_cast<Usage *>(a->alloc());
b->print();
delete a;
delete b;
}
}
Hope it helps.
In C++, is there any way to query the type of an object...
Yes, use typeid() operator
For example:
// typeid, polymorphic class
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
class CBase { virtual void f(){} };
class CDerived : public CBase {};
int main () {
try {
CBase* a = new CBase;
CBase* b = new CDerived;
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
cout << "*a is: " << typeid(*a).name() << '\n';
cout << "*b is: " << typeid(*b).name() << '\n';
} catch (exception& e) { cout << "Exception: " << e.what() << endl; }
return 0;
}
Output:
a is: class CBase *
b is: class CBase *
*a is: class CBase
*b is: class CDerived
If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception
Read more.....
class Base
{
public:
virtual ~Base() { }
};
class Foo : public Base
{
};
class Bar : public Base
{
};
template<typename T1, typename T2>
T1* fun(T1* obj)
{
T2* temp = new T2();
return temp;
}
int main()
{
Base* b = new Foo();
fun<Base,Foo>(b);
}
When there are extremely many classes deriving from the same base class then this code will save you from having to include clone methods every class. It's a more convenient way of cloning that involves templates and an intermediate subclass. It's doable if the hierarchy is shallow enough.
struct PureBase {
virtual Base* Clone() {
return nullptr;
};
};
template<typename T>
struct Base : PureBase {
virtual Base* Clone() {
return new T();
}
};
struct Derived : Base<Derived> {};
int main() {
PureBase* a = new Derived();
PureBase* b = a->Clone(); // typeid(*b) == typeid(Derived)
}