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.
Related
I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}
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")
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;
};
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.
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)
}