I have two classes, one of which is a subclass of another, and differs only by the fact that it contains an additional member variable to its parent. I am not using the default constructor, passing in a reference to a single object as the constructors parameter. What I would like is for the constructor of the parent to examine this object, and then determine whether to construct an instance of the parent class (in most cases) or the subclass (in a few specialised cases).
class Superclass
{
public:
Foo foo;
Superclass(MyObject* object)
{
foo = object->GetFoo();
if(object->CreateSubclass())
{
//Create Subclass
}
else
{
//Create Superclass
}
}
};
class Subclass : public Superclass
{
public:
Barr barr;
Subclass(MyObject* object)
{
barr = object->GetBarr();
}
};
I'm aware of the factory design pattern, but don't want to have to have a factory object just for this. I'd rather duplicate the Superclass initialisation stuff into the Subclass (which seems bad) and then examine the object at each of the points where a Superclass is created and then call the appropriate constructor:
Superclass* class;
if(object->CreateSubclass())
{
class = new Subclass(obj);
}
else
{
class = new Superclass(obj);
}
Is this sort of thing possible, and if so how would I go about calling the subclasses constructor from Superclass constructor? I've tried making a call to Subclass(object), but I run into issues with both Superclass and Subclass needing to be defined before the other.
Thanks for any advice you can provide.
If you're set against a factory class, why not just a static function?
class Subclass
{
public:
static Superclass* create(const MyObject* const object)
{
if (object->createSubclass())
{
return new Subclass(object);
}
else
{
return new Baseclass(object);
}
}
// ...
}
// ...
Superclass* const myInstance = Subclass::create(myObject);
(I've put the static class in Subclass because it needs both the super and subclass implementations, but you could easily put it in a shared namespace or something, or even put the declaration in the base class but put the implementation in a cpp)
You've now got most of the benefits of a factory class, with no more code than you had before. You're just missing the ability to pass it around or easily refactor it into multiple implementations.
I think this is impossible. The object is allocated before the constructor is called. Otherwise there would be no 'this' pointer and you couldn't initialize your variables. Think about it. Also notice that constructors don't return anything, yet the output of new YourClass() is a pointer to your new object.
Related
This is what I want to do:
class Derived : public Base
{
public:
int someNewMethod(int someIntParam)
{
// Does something not in the base class
return 0; // success
}
};
Then I should be able to use Derived in place of Base (while fully aware that the reference may become invalid, depending on when the Base object is deleted):
Derived &d = *pointerToSomeExistingBaseObject;
d.someNewMethod(12);
While somewehere else in code, far, far away (and beforehand):
Base *pointerToSomeExistingBaseObject = new Base(...);
Thank you!
Create a fully-functional derived class with just one extra method in C++?
You can do that. You did that with Derived (assuming someNewMethod isn't in Base).
Derived &d = *pointerToSomeExistingBaseObject;
d.someNewMethod(12);
While somewehere else in code, far, far away (and beforehand):
Base *pointerToSomeExistingBaseObject = new Base(...);
No, you cannot do that. In order to call the non-static member functions of Derived, you must create an object of type Derived or a type derived from it.
The typical solution is to make the function free-standing:
int someNewMethod(Base& obj, int someIntParam)
{
// Does something with obj that is not in Base
return 0; // success
}
I have a "chain" class, meaning a class that manages a sequence of objects with a common base class.
This chain class should execute the member function processSample(a, b) for any child class (of baseClass) I add.
I want to be able to code more child classes (with a processSample(a, b) function) later on, and add them to the chain without having to edit the chain class.
I could use a template in the add function but this doesn't solve the problem that there is no data structure for different datatypes (of different sizes) right?
Functions of the children called in the Chain class should all be overridden virtuals from the base class.
class baseClass
{
public:
virtual float processSample(int a, float b)
{
}
};
class Chain
{
const int maxChilds = 20;
?sometype? allChilds[maxChilds];
public:
float processSample(int c, float d)
{
for (int i = 0; i < maxChilds; i++)
{
input = allChilds[i].processSample(a, b);
}
return input;
}
void addChild(?sometype? newChild)
{
allChilds.push_back(newChild)
}
}
You would want to use pointers or references, to avoid initialization or copy operations as part of creating the class.
For example
class Chain
{
const int maxChilds = 20;
baseClass allChilds[maxChilds];
Will create, and initialize an array of 20 baseClass instances. Whereas this:
class Chain
{
const int maxChilds = 20;
baseClass* allChilds[maxChilds];
Will create an array of pointers to baseClass, which can also point to instances of any child classes. Do consider which class will be responsible for allocation and de-allocation of the memory for these instances (this can either be within this class, or the caller / user of this class - which one is ideal will depend on the rest of your design). You could also consider using a smart pointer instead and let that manage the memory for you: https://en.cppreference.com/book/intro/smart_pointers
Similarly:
void addChild(baseClass newChild)
Will use pass-by-value to pass in a copy of newChild (using the copy constructor of baseClass), any instances of child classes will either fail or be converted to an instance of baseClass. Whereas if you instead go with:
void addChild(baseClass& newChild)
It will use pass-by-reference instead, and the function will receive a reference to the original object.
The nice effect of virtual is, that you "call a function of the base class", but the function of the derived class will be executed.
So ?sometype? allChilds[maxChilds]; is baseClass allChilds[maxChilds];. The chain should be the holder of the objects, so addChild(...) should not accept an instance of the child-class. It should create the instance and use (if necessary) std::move to add it to the array.
Remark: It will be easier for you using
std::vector<baseClass>allChilds;
allChilds.reserve(maxChilds); //reserves the memory but you can still use push back
I've run into a problem with copy constructors...I assume there is a basic answer to this and I'm missing something obvious - maybe I'm doing something entirely wrong - but I haven't been able to figure it out.
Basically, I have a parent class and child class. The parent class contains a vector of pointers to a (different) base class object. The child class wants to instead store pointers to objects derived from that base object.
Here's a pseudocode sample, if that helps:
// Base classes
class ItemRev {
...
}
class Item {
protected:
vector<ItemRev *> m_revPtrVec;
}
Item::Item(const Item &inputItemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revPtrVec).begin();
while (vecIter != (inputItemObj.m_revPtrVec).end()) {
(this->m_revPtrVec).push_back(new ItemRev(**vecIter));
}
}
=========
// Derived classes
class JDI_ItemRev : public ItemRev {
...
}
class JDI_Item : public Item {
...
}
JDI_Item::JDI_Item(const JDI_Item &itemObj)
{
// Copy contents of the input object's item rev pointer vector
vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revObjPtVec).begin();
// The below does not work!
while (vecIter != (inputItemObj.m_revObjPtVec).end()) {
m_revObjPtVec.push_back(new JDI_ItemRev(**vecIter));
}
}
The problem with the above is in the push_back() call in the JDI_Item copy constructor.
Given this setup, what should the child class's copy constructor look like? Do I even need a child class copy constructor? I assumed I did, because the copy constructor is creating new objects, and the parent copy constructor will create new objects that are not the type I want in the derived class (i.e., the parent object stores pointers to ItemRev objects, while the child object should store pointers to derived JDI_ItemRev objects).
As mentioned in the comments, there is probably a more succinct way to express this problem (i.e. your class structure needs some work).
However, if you want to do it this way, the easiest way to achieve it is to use a virtual clone() method in the base class of ItemRev, with overrides of it defined in derived classes.
e.g.:
class ItemRev {
virtual ItemRev* clone() const = 0;
};
class JDI_ItemRev : public ItemRev {
ItemRev* clone() const override
{
// do your actual cloning here, using the copy constructor
return new ItemRev(*this);
}
};
Now, whenever you call clone() on any class derived from ItemRev, you will be returned an ItemRev* but it will point to a fully constructed derived class. You can of course get to the derived class's interface with static_cast<> or dynamic_cast<>.
...however...
derivation often seems like an easy win but it often turns out not to be. Inheritance should only be used if the derived class really is a type of the base class. Often people select inheritance when the derived class is a lot like a base class, or shares many characteristics with a base class. This is not the time to use inheritance. It's the time to use encapsulation.
In general, inheritance is evil.
On another note, you might find this link interesting.
Presentation on inheritance as an implementation detail
I am trying to access a method of derived class from the object of my base class. I have a base class CBase which is an abstract class,
class CBase{
protected:
char path[255];
public:
virtual void StartBackup()=0;
void setpath(char * path)
{
strcpy(this->path,path);
}
virtual void afunc()
{
printf("Base\n");
}
};
Now two classes Ctype1 and Ctype2 are derived classes from CBase
class CType1:public CBase{
public:
void StartBackup()
{
printf("Type1:%s",path);
}
void afunc()
{
printf("CType1:afunc\n");
}
void myfunc()
{
printf("myfunc\n");
}
};
class CType2:public CBase{
public:
void StartBackup()
{
printf("Type2:%s",path);
}
void afunc()
{
printf("type2:afunc\n");
}
void typefunc()
{
printf("typefunc\n");
}
};
I have a class CManager which has an object of class CBase as its member,
class CManager{
private:
CBase * obj;
public:
CManager(){
obj = NULL;
}
~CManager(){
if(obj)
delete obj;
obj = NULL;
}
void inittype(int type)
{
if(type == 1)
{
obj = new CType1();
obj->myfunc();
}
else
{
obj = new CType2();
obj->typefunc();
}
}
};
In void inittype(int type) function i take the input as type and initialize the CBase object accordingly.
The problem that i am facing is that after creation of object when i try to access myfunc or typefunc i get compilation errors. How can i access these functions(I Dont want to create these functions in the base class)?
EDIT :
The errors that i get are,
'myfunc' : is not a member of 'CBase'
'typefunc' : is not a member of 'CBase'
Thanks
If you only need to access the classes non-derived functions at creation time, then this will work
void inittype(int type)
{
if(type == 1)
{
CType1* temp = new CType1();
temp->myfunc();
obj = temp;
}
else
{
CType2* temp = new CType2();
temp ->typefunc();
obj = temp;
}
}
If you need to access these member functions at other times, you'll need to use a cast - e.g.
CType2* child = dynamic_cast<CType2*>(obj);
Create an inittype virtual function in your base class (doing nothing), then override it in the derived classes as you need.
void CType1::inittype() {
myfunc();
}
void CType2::inittype() {
typefunc();
}
void CManager::inittype(int type)
{
if(type == 1)
{
obj = new CType1();
}
else
{
obj = new CType2();
}
obj->inittype();
}
I'm not clear what you mean by "I Dont want to create these functions in the base class".
You appear to know about pure virtual functions. If you declared the problem functions as pure functions in CBase, you should be able to call them through a CBase * pointer.
One possible confusion in object-oriented languages is that "what type is this" has two answers depending on context. When you create a new object, the type is the exact type. When you access an existing object via a reference or pointer, the type is a set of possible types - the base class and all subclasses the might exist. More precisely, the type of the pointer/reference defines the interface you can use to access the object. That interface must be known without reference to the derived classes (which may not exist when the base class is compiled) so it must be declared in the base class - the virtual methods.
If you want to call something that's only known in the derived class, there are two options. One is to not forget the derived class in the first place. For example...
CType1 *temp = new CType1();
obj = temp;
temp->myfunc();
The other is to determine which derived class you're using at run-time, and use a cast to convert the pointer. The (relatively) safe way to do this is with dynamic_cast.
CType1 *temp = dynamic_cast<CType1> (obj);
if (temp) { temp->myfunc (); }
I haven't covered how you identify the type at run-time. There's "Run-Time Type Identification" (RTTI) built into C++ to do this, but I've very rarely used it. In the rare cases where dynamic_cast is the right thing, I've always known the type for some other reason - either the objects were in a closed set of classes that could be identified via functionality in some interface anyway, or there was only one possibility that could occur in the code that needed the dynamic_cast.
The key words here are "closed set of classes" - if someone else inherits from your classes, you can have unexpected problems when objects of a type you don't know about and therefore cannot identify are accessed by your code. That isn't really a problem with OOP, it's a designed-in feature - you're supposed to be able to extend existing classes in OOP without notifying whoever wrote the base classes, that's what inheritance is for. Though in languages where you can mark a class final, that's probably a good idea if you don't want to allow it in this case (and IIRC C++11 provides a way to do that, I just don't know how to spell it).
i am pretty sure this is a simple question for a long time c++ user, this should be a pattern or the problem should be solved in any other way but given i am Python developer and a total novice with c++ i don't know how it's usually done.
Suppose that i have a class where i want to store a pointer to an object that can be of 1 of two different classes that respects an interface, for example:
class AllPlayers
{
public:
virtual void play();
};
class VlcPlayer: public AllPlayers
{
public:
virtual void play();
};
class Mplayer: public AllPlayers
{
public:
virtual void play();
};
class MyMediaPlayer
{
public:
MyMediaPLayer(int playerType);
AllPlayers m_player;
};
MyMediaPlayer::MyMediaPlayer(int PlayerType)
{
if (PlayerType == 0) {
VlcPlayer tmp_player;
m_player = static_cast<AllPlayers> (tmp_player);
}
else {
Mplayer tmp_player;
m_player = static_cast<AllPlayers> (tmp_player);
}
}
MyMediaPlayer test(0);
test.play();
First, i know this would not work and that it seems pretty normal why but how could i get this effect? i would like to have a member of a class for what i am going to use ever the same methods, implemented using a interface and i would like to avoid trying to cast to every of the derived classes every time i am going to use one of his methods.
C++ is value-based, i.e., if you create an object of a given type you really have an object of this type. This doesn't play nicely with dynamic polymorphism. To get dynamic polymorphism you use a pointer or a reference to the actual object. To also get the life-time straight you typicslly allocate the corresponding object on the stack (make sure your base class has a virtual destructor if you ever release an object of a derived type using a pointer to the base). With this, you should be all set: just call a virtual function of the base class through a pointer to rhe base: When you overridethe function in the derived class this is the function which is called.
If you write
AllPlayers m_player;
that is going to be an instance of AllPlayers and cannot be an instance of a class that derives from it.
You should instead use a pointer and allocate the class on the stack.
For example:
class MyMediaPlayer
{
public:
MyMediaPLayer(int playerType);
~MyMediaPLayer();
AllPlayers m_player;
};
MyMediaPlayer::MyMediaPlayer(int PlayerType)
{
if (PlayerType == 0) {
m_player = new VlcPlayer;
}
else {
m_player = new Mplayer;
}
}
MyMediaPlayer::~MyMediaPlayer()
{
if (0 != m_player) {
delete m_player;
m_player = 0;
}
}
As suggested by #xception use of unique_ptr may relieve you from having to write code to deallocate the instance.
As correctly pointed out by #DietmarKühl you should always declare a virtual destructor in a root class (a base class that does not itself derives from some other class) as is the case with AllPlayers.
class AllPlayers
{
public:
virtual ~AllPlayers();
virtual void play(); // note: this should probably be pure virtual.
};
The reason this will not work is colloquially known as Object Splicing. (Or, for those Harry Potter readers out there, Object Splinching)
Let's look at an example:
class Foo
{
public:
int bob;
float fred;
// Foo(const Foo& otherfoo); // implicit copy constructor
};
class Bar : public Foo
{
public:
double gabe; // gabe newell is fat
char steve; // steve jobs is thin
// Bar(const Bar& otherbar); // implicit copy constructor
};
int main()
{
Foo f;
Bar b;
f.bob = 10;
f.fred = 1.5;
b.bob = 15;
b.fred = 2.5;
b.gabe = 1.77245385091; // sqrt(pi)
b.steve = -4;
f = Foo(b);
return 0;
}
This is legal and valid. Problem is, the implicit copy constructor of Foo is called, and Foo's copy constructor knows nothing about what a Bar is. Only that it contains everything a Foo has, and some extra irrelevant crap. Because of this, only the Foo's data gets preserved; the data unique to the Bar gets spliced off.
It's important to note that this is DEFINED BEHAVIOR: it's doing EXACTLY WHAT YOU TELL IT TO. Casting between a subclass of a base class and a base class is implicit. Furthermore, the behavior of the copy constructor is implicit.
It's also important to note that, under the hood, C++ pointers and references work in the same way. It's perfectly sane to pass the Bar to Foo's copy constructor by reference, this pass by reference does not produce a copy of the object. It's the same as working with a pointer.
The actual splicing takes place as a direct result of the copy constructor biting off more than it can chew. It gets an object with more state than it expected, and its only choice is to ignore the extra state.
With python, this doesn't happen because everything is implicitly stored as a reference type. Since you only work with references (the objects themselves are abstracted away), you never have the opportunity to accidentally splice an object.