For any reason, I have an object created by a static method which calls the private constructor. (It isn't a singleton)
I want to make a new object derives from the first one, which have more members and functions.
But it's problematic, becuase the static method returns a firstObject* object, so a creation with downcasting of the secondObject* will make a memory overflow.
What should I do? I have an access to the first object's code, but it is impossible to change its constructor (If I change it, I will have to change a huge written code).
EDIT:
Thank to all responders. I can change the constructor to be protected.
Make sure your constructor is at least protected so that child classes can use it.
Not sure what you fear about memory overflow but this:
class Base {
public:
static Base* getInstance();
virtual ~Base() {};
protected:
Base() {};
};
class Derived : public Base {};
// Implementation
Base* Base::getInstance() { return new Derived(); }
int main() {
Base::getInstance();
};
Works perfectly.
Now I would advise you against returning a raw pointer in that situation (std::unique_ptr would be way better) but that's probably off-topic.
Related
As per this article, which says that[emphasis mine]:
Making base class destructor virtual guarantees that the object of derived class is destructed properly, i.e., both base class and derived class destructors are called.
As a guideline, any time you have a virtual function in a class, you should immediately add a virtual destructor (even if it does nothing). This way, you ensure against any surprises later.
I think even if your base class has no virtual function,you should either add a virtual destructor or mark the destructor of the base class as protected.Otherwise, you may face memory leak when trying to delete a pointer pointed to a derived instance. Am I right?
For example,here is the demo code snippet:
#include<iostream>
class Base {
public:
Base(){};
~Base(){std::cout << "~Base()" << std::endl;};
};
class Derived : public Base {
private:
double val;
public:
Derived(const double& _val){};
~Derived(){std::cout << "~Derived()" << std::endl;}; //It would not be called
};
void do_something() {
Base* p = new Derived{1};
delete p;
}
int main()
{
do_something();
}
Here is the output of the said code snippet:
~Base()
Could anybody shed some light on this matter?
The behavior of the program in the question is undefined. It deletes an object of a derived type through a pointer to its base type and the base type does not have a virtual destructor. So don't do that.
Some people like to write code that has extra overhead in order to "ensure against any surprises later". I prefer to write code that does what I need and to document what it does. If I decide later that I need it to do more, I can change it.
This question will lead to a bunch of other questions about whether a programmer should always be super safe by protecting its code even against currently non existent problems.
In your current code, the Derived class only adds a trivial double to its base class, and a rather useless destructor, that only contains a trace print. If you deleted an object through a pointer to the base class, the Derived destructor will not be called, but it will be harmless. Furthermore, as you were told in the comment, using polymorphism (casting a pointer to a base class one) with no virtual function does not really makes sense.
Long story made short, if you have a class hierarchy with no virtual function, users are aware of it and never delete an object through a pointer to its base class. So you have no strong reason to make the destructor virtual nor protected. But IMHO, you should at least leave a comment on the base class to warn future maintainers about that possible problem.
Without a virtual destructor your call to delete is arguably wrong. It should be:
void do_something() {
Base* p = new Derived{1};
Derived *t = dynamic_cast<Derived*>(p);
if (t) {
delete t;
} else {
delete p;
}
}
You can use up/down casting of objects to store them in a common array or vector and still be able to call methods of the derived objects all without a virtual destructor. It's usually a sign of bad design but it is legal C++ code. The cost is that you have to do cast back to the original types before delete like above.
Note: The dynamic_cast can only be done when Base has at least one virtual function. And if you have a virtual functions you should just add the virtual destructor.
And if you don't need to dynmaic_cast anywhere then show me case where you can't use an array of Base instead of Base *.
The point of making the destructor of the base class protected I guess is to generate an error when someone deletes a Base* so you can then make the destructor virtual. Means you don't have the overhead of a virtual destructor until you actually need it.
fwiw it's happening because you try to delete it through Base. if you somehow really want to have object reference/pointer of only the base type, there are some alternatives.
void do_something() {
Base&& b = Derived{1};
}
void do_something() {
Derived d{1};
Base* p = &d;
Base& b = d;
}
void do_something() {
std::shared_ptr<Base> sb = std::make_shared<Derived>(1);
}
// NOTE: `std::unique_ptr` doesn't work
void do_something() {
std::unique_ptr<Base> ub = std::make_unique<Derived>(1); // warning: this not work
}
This is probably a simple question, please bear with me since I'm used to Java...
Lets say we have an interface:
class IDoable {
virtual void do() = 0;
};
Another class:
class Base : public IDoable {
//...
virtual void do() { ... }
};
And a last class extending our base class:
class ExtendingBase : public Base {
// some extra functionality
};
I am lost at the part if I want to make a list of IDoable objects, which can be Base objects or ExtendingBase objects. Do I have to add some method declaration of the methods in the Base class? How does this aspect work?
EDIT:
I have someList of type IDoable pointers
and if I then try to add a Base object to that list I get the error:
IDoable is an ambiguous base of Base
Same if i try to add an ExtendingBase object
IDoable is an ambiguous base of ExtendingBase
Since do is a pure virtual method, it will have to be implemented in a derived class. You can't have a vector or array of IDoable objects because you can't instantiate such an object. You can have a vector or array of pointers or references to objects though.
If you create an ExtendingBase object and call the do function, it will call the Base class' one (since ExtendingBase inherits that method).
Virtual polymorphism enters into play when you call the do() function from a base class pointer or reference: the do() function appropriate to the dynamic type of the object pointed or referenced to will be called:
class IDoable{
public:
virtual void dof()=0;
virtual ~IDoable() = default;
};
class Base:public IDoable{
public:
virtual void dof(){std::cout << "Base";}
virtual ~Base() = default;
};
class ExtendingBase:public Base{
public:
virtual void dof() { std::cout << "ExtendingBase"; }
};
int main()
{
IDoable *ptr = new Base(); // A smart pointer would be a better choice
// but for clarity's sake I'm using bare
// memory allocations here
ptr->dof(); // Walks the virtual table and calls "Base"
delete ptr;
ptr = new ExtendingBase();
ptr->dof(); // Walks the virtual table and calls "ExtendingBase"
delete ptr;
}
Also notice the use of virtual destructors: they work like normal virtual functions and thus when calling delete on a base pointer, in order to actually destruct the right type of object (i.e. to call the right destructor in the hierarchy), you will need to make it virtual.
As a sidenote: do is a reserved keyword in C++
In response to your edit: if you have a vector or a list of IDoable pointers, you can't just add a derived object to it, but you should add a pointer to a derived object. I.e. the following is wrong:
std::vector<IDoable*> vec;
vec.push_back(Base());
plus a base class remains a class (there is no interface concept in C++ as in Java) and you shouldn't inherit from a base class multiple times:
class Base:public IDoable{
...
class ExtendingBase:public Base, public IDoable <- nope
...
that would only cause issues in identifying the base subobject.
I recommend to read about the dreaded diamond problem in C++ (it's a way to solve a base class appearing multiple times in the inheritance hierarchy.. anyway a good design might probably avoid this in the first place).
if I want to make a list of IDoable objects
You cannot make an IDoable object period. It's an abstract class, it cannot be constructed directly, so you cannot have a container of them. What you can do and what you likely intend is to have a container of IDoable*:
std::vector<IDoable*> objects;
objects.push_back(new Base);
objects.push_back(new ExtendedBase);
Or to express ownership better in C++11:
std::vector<std::unique_ptr<IDoable>> objects;
Given your interface, you can already call do() on any of these objects and that will do the right thing via virtual dispatch. There is one member function you definitely want to add to your interface though:
class IDoable {
public:
virtual ~IDoable() = default; // this one
virtual void do() = 0;
};
That way, when you delete an IDoable*, you will delete the full object, not just the base interface.
You will have to implement your do() function in Base, since the function in the class IDoable is pure virtual.
If you decide to create an ExtendingBase object, the do() function will behave as it's implemented in Base, unless you override it by re-implementing it in ExtendingBase.
the first and most major of your problem is that your thinking in Java.
the words "interface" and "extending" are very Java oriented. C++ does not think this way.
for example, when someone talks about an "interface" in a C++ context, I may think he talks about the class decleration inside the .h file (as opposed to the implementation which lies in the .cpp file)
IDoable is a CLASS. period. the only difference is that it has a pure virtual functions that prohibits instansiation. other than that it behaves as a class, it can be inherited from, can hold member variables and anything else.
you just need to make sure the abstract function is overriden in some derived class in order for that class to produce objects.
thus said :
//in the stack:
Base base;
ExtendingBase eBase;
base.do();
eBase.do()
//in the heap with IDoable as pointer:
IDoable * base = new Base();
IDoable * ebase = new ExtendingBase ();
base->do();
ebase->do();
now, you may ask - how do I activate Base and ExtendingBase functions? so just like Java, you need to cast the pointer and only then call the right function.
Base* realBase = (Base*)base;
realbase->someBaseFunction();
as many things in C++, this code is a bit dangerous. you can use dynamic_cast instead.
and one last thing - do is a keyword in C++, it cannot declare a function name.
IDoable *pDo1 = new Base();
IDoable *pDo2 = new ExtendingBase();
pDo1->do();
pDo2->do();
delete pDo1;
delete pDo2;
Do C++ compilers generate the default functions like Constructor/Destructor/Copy-Constructor... for this "class"?
class IMyInterface
{
virtual void MyInterfaceFunction() = 0;
}
I mean it is not possible to instantiate this "class", so i think no default functions are generated.
Otherwise, people are saying you have to use a virtual destructor.
Which means if i dont define the destructor virtual it will be default created, not virtual.
Furthermore i wannt to know if it is reasonable to define a virtual destructor for a pure virtual Interface, like the one above? (So no pointers or data is used in here, so nothing has to be destructed)
Thanks.
Yes.
There is no wording that requires the class to be instantiable in order for these special member functions to be implicitly declared.
This makes sense — just because you cannot instantiate the Base, doesn't mean a Derived class doesn't want to use these functions.
struct Base
{
virtual void foo() = 0;
int x;
};
struct Derived : Base
{
Derived() {}; // needs access to Base's trivial implicit ctor
virtual void foo() {}
};
See:
§12.1/5 (ctor)
§12.8/9 (move)
§12.8/20 (copy)
Furthermore i wannt to know if it is reasonable to define a virtual destructor for a pure virtual Interface, like the one above? (So no pointers or data is used in here, so nothing has to be destructed)
It's not only reasonable, it's recommended. This is because in the case of virtual function hierarchies, (automatically) calling a destructor of a specialized class also calls all destructors of it's base classes. If they are not defined, you should get a linking error.
If you define at least one virtual function in your class you should also define a virtual destructor.
The destructor can be defined with =default though:
Here's a corrected (compilable) code example:
class ImyInterface
{
virtual void myInterfaceFunction() = 0;
virtual ~ImyInterface() = 0;
}
ImyInterface::~ImyInterface() = default;
Furthermore i wannt to know if it is reasonable to define a virtual destructor for a pure virtual Interface, like the one above? (So no pointers or data is used in here, so nothing has to be destructed)
Will the derived classes ever do anything in their destructors? Can you be certain they never will, even when somebody else takes over development?
The whole point of having a virtual destructor is not to make sure the base class is properly destructed, that will happen anyway. The point is that the derived class's destructor is called when you use a generic interface:
struct A {
virtual ~A() {}
virtual int f() = 0;
};
class B : public A {
std::ifstream fh;
public:
virtual ~B() {}
virtual int f() { return 42; }
};
std::shared_ptr<A> a = new B;
When a goes out of scope, why is the ifstream closed? Because the destructor deletes the object using the virtual destructor.
This addresses the second question about declaring a virtual destructor for an abstract base class (e.g. at least one member function is pure virtual). Here is a real world example of the LLVM clang++ compiler catching a potential problem. This occurred with the command line tools version supplied by Apple Developer for the Mac OS X Mavericks operating system.
Suppose you have a collection of derived classes that ultimately have the parent with the abstract base class to define the common interface. Then it is necessary to have a storage container like a vector that is intentionally declared to store a pointer to the abstract base class for each element. Later on, following good engineering practices, the container elements need to be "deleted" and the memory returned to the heap. The simplest way to do this is to traverse the vector element by element and invoke the delete operation on each one.
Well, if the abstract base class does not declare the destructor as virtual, the clang++ compiler gives a friendly warning about calling the non-virtual destructor on an abstract class. Keep in mind that in reality only the derived classes are allocated from the heap with operator new. The derived class pointer type from the inheritance relationship is indeed the abstract base class type (e.g. the is-a relationship).
If the abstract base class destructor is not virtual, then how will the correct derived class' destructor be invoked to release the memory? At best the compiler knows better (at least potentially does with C++11), and makes it happen. If the -Wall compiler option is enabled, then at least the compilation warning should appear. However, at worse, the derived class destructor is never reached and the memory is never returned to the heap. Hence there is now a memory leak that may be very challenging to track down and fix. All it will take is a single addition of "virtual" to the abstract base class destructor declaration.
Example code:
class abstractBase
{
public:
abstractBase() { };
~abstractBase() { };
virtual int foo() = 0;
};
class derived : abstractBase
{
public:
derived() { };
~derived() { };
int foo() override { return 42; }
};
//
// Later on, within a file like main.cpp . . .
// (header file includes are assumed to be satisfied)
//
vector<abstractBase*> v;
for (auto i = 0; i < 1000; i++)
{
v.push_back(new derived());
}
//
// do other stuff, logic, what not
//
//
// heap is running low, release memory from vector v above
//
for (auto i = v.begin(); i < v.end(); i++)
{
delete (*i); // problem is right here, how to find the derived class' destructor?
}
To resolve this potential memory leak, the abstract base class has to declare its destructor as virtual. Nothing else is required. The abstract base class now becomes:
class abstractBase
{
public:
abstractBase() { };
virtual ~abstractBase() { }; // insert virtual right here
virtual int foo() = 0;
}
Note that the abstract base class has currently empty constructor and destructor bodies. As Lightness answered above, the compiler creates a default constructor, destructor, and copy constructor for an abstract base class (if not defined by the engineer). It is highly recommended to review any of The C++ Programming Language editions by the C++ creator, Bjarne Stroustrup, for more details on abstract base classes.
This example below illustrates how to prevent derived class from being copied. It's based on a base class where both the copy constructor and copy assignment operator are declared private.
class Uncopyable
{
protected:
// allow construction and destruction of derived objects...
Uncopyable() {}
~Uncopyable() {}
private:
// but prevent copying...
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
We can use this class, combined with private inheritance, to make classes uncopyable:
class derived: private Uncopyable
{...};
Notice that the destructor in class Uncopyable is not declared as virtual.
Previously, I learned that
Destructors in base classes should be virtual.
Destructors in non-base classes should not be made virtual.
In this example, the destructor for Uncopyable is not virtual, but it is being inherited from. This seems to go against the wisdom I've learned previously.
When and why should destructor in base class NOT be defined as virtual?
A base class destructor only needs to be virtual if you might try deallocating an object of a derived type through a pointer of the base type. Consequently, if you only inherit from the base class privately instead of publicly, as would be the case in Uncopyable, then you don't need to worry about putting in a virtual destructor, because when using private inheritance you can't get a pointer to the derived object and store it in a pointer to the base type.
Another example might be if you were to use a mixin class like this one that makes a class track the number of object allocations, where the mixin is inherited from to acquire behavior but not to be treated polymorphically:
template <typename T> class Counter {
public:
Counter() { ++numInstances; }
Counter(const Counter&) { ++numInstances );
~Counter() { --numInstances; }
static unsigned getNumInstances() { return numInstances; }
private:
static unsigned numInstances;
}
template <typename T> unsigned Counter<T>::numInstances = 0;
More generally, when using static polymorphism, you don't need virtual destructors because you never treat the classes polymorphically using pointers to the base type. You only use a pointer to the derived type.
There are probably a few other cases I didn't cover here, but these two (private inheritance, mixin classes, and static polymorphism) cover much of the space where virtual destructors aren't required.
When you design the base not as interface, but as implementation detail (note the private inheritance from Uncopyable).
You technically don't have to make your decostructor virtual if you know nobody will delete it as a Uncopyable*, but will always delete it as a subclass of the same.
Yes this is essentially, what #templatetypedef said, but I'm going to explain it in a maybe easier way.
So: if people might do something like this:
void aFunction(Uncopyable* obj) {
delete obj;
}
Then you should declare your destructor virtual (to make sure potential subclasses get their destructor called.
However, if you know people will be deleting Subclasses like so:
class Widget : public Uncopyable
{
....
};
void aFunction(Widget* obj) {
delete obj;
}
Then you don't have to make your destructor virtual (as the subclasses destructor will be called).
At least, that's my understanding.
When you need your objects to be plain old data, with no vtable. I'd comment the heck out of it if I ever needed it, as 99% of the time leaving off the 'virtual' in base class destructors is simply a mistake that someone will want to correct.
The general rule is to make your destructor public and virtual, or protected and non-virtual. In the first case, your object use destroyable polymorphically and teh virtual destructor will do the right thing. In the second case it will only be destroyed as the actual child class and still do the right thing.
Is it legal? If so, do you consider it as good coding practice?
I want to do something like this (nonessential details are not shown):
class ItemStorage {
int size() const;
};
class SpecialStorage : public ItemStorage {
public:
SpecialStorage (...) : ItemStorage(...), items(ItemStorage::size()) {...}
private:
int items;
};
I am pretty sure that it is OK if the method size is not virtual. What if it is virtual and the derived class doesn't overwrite it?
The general rule is that, during initialization, you must not access uninitialized parts of the object. As ItemStorage is already initialized when items gets initialized, calling size is indeed fine.
Even if size was virtual, and even if it was overwritten, it still would be fine: it would just call the base version (i.e. virtual methods only bind to the level which is under construction).