Disallow slicing to keep multiple parent class properties in sync - c++

I am deriving an object from two parent classes. These two parents each have different types of properties, but I want the child to keep them in sync with each other. However, I want to disallow users of the library from treating Child like a ParentA or a ParentB accidentally via slicing. For example:
#include <iostream>
class ParentA
{
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class ParentB
{
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class Child : public ParentA, public ParentB
{
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
ParentA::modify();
ParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
This call to Change(child); calls ParentA's modify() function, in which the ParentA properties can get out of sync with the ParentB properties, leaving the Child in a bad state.
There are many functions (the read*() ones here) in ParentA and ParentB that I don't want to have to manually forward from Child, so I can't derive privately.
Is there a way to make this call to Change(child) produce a compiler error (without changing the signature of Change)?

There is in fact a way to do this (although said you didn't like it): private or protected inheritance is the C++ mechanism to achieve what you want.
Bear in mind that since your child class is trying to keep some sort of invariant between A and B, if you inherit publicly, someone will find a way to use A or B's interface to violate the invariant anyway so you need to protect against those being used in the child directly, which the restricted inheritance does perfectly.
If there are then some methods in the parent that don't affect the two-class invariant you can using those down into the public section of Child.

As the comments already say the cleanest way might be to just inherit from ParentA and ParentB with private and forward the needed functions.
I had another idea: You could extract the functionality of ParentA and ParentB into 2 abstract classes (AbstractParentA,AbstractParentB) and use these classes as base classes.
This would give you the desired behaviour:
#include <iostream>
class AbstractParentA
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class AbstractParentB
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class ParentA : public AbstractParentA
{
virtual void no_instance() override {}
};
class ParentB : public AbstractParentB
{
virtual void no_instance() override {}
};
class Child : public AbstractParentA, public AbstractParentB
{
virtual void no_instance() override {}
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
AbstractParentA::modify();
AbstractParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
error C2664: 'void Change(ParentA)': cannot convert argument 1 from 'Child'
note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Related

Nested struct attributes inheritance

I read that you can extend a structure by using inheritance. I have a derived class in which I want to have the same struct that its parent but extended with more fields. This seems to work, however when I call a method from the Parent class that modified the structure, it does not have effect in the Child structure attribute. Here, an example of what am I trying:
class Parent
{
public:
struct info
{
int a;
};
info data;
virtual void main(void);
};
void Parent::main()
{
data.a =1;
}
class Child: public Parent
{
public:
struct info2: public info
{
int b;
};
info2 data;
virtual void main(void);
};
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << data.a << "\n";
std::cout << data.b << "\n";
}
int main(void)
{
Parent *base;
Child derived;
base = &derived;
base->main();
return 0;
}
This instead of printing 1 and 2 prints 0 and 2. So basically as if the attribute data from the derived class is not modified by the call to Parent::main.
What the right way of doing that? Am I completely doing it wrong?
You mean
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << Parent::data.a << "\n";
std::cout << data.b << "\n";
}
The name data declared in the derived class hides the name data declared in the base class. So you need to use a qualified name to access a hidden member of the parent class.
As for data member a of the member data of the derived class then it was not initialized.
Objects of the derived class have two data members data: one is inherited with the type info (which name is hidden in the derived class) and other is the own data member of the derived class.
The base class knows nothing about the data member data of the derived class.
You could define a virtual function within the class info. For example
#include <iostream>
class Parent
{
public:
struct info
{
int a;
virtual void set( int a )
{
this->a = a;
}
};
info data;
virtual void main(void);
};
void Parent::main()
{
data.set( 1 );
}
class Child: public Parent
{
public:
struct info2: public info
{
int b;
void set( int a ) override
{
this->a = a;
}
};
info2 data;
virtual void main(void);
};
void Child::main(void)
{
data.set( 3 );
data.b = 2;
std::cout << data.a << "\n";
std::cout << data.b << "\n";
}
int main(void)
{
Parent *base;
Child derived;
base = &derived;
base->main();
return 0;
}
The program output is
3
2
You're entirely correct, Parent::main() is unable to access Child::data, and knows nothing about any mythical info2 type; to it, Parent::data is all there is, and info is its type.
There are a few easy ways to make Child::main() work with Child::data instead of Parent::data, or to make it access the desired field from each version, but I suspect that's not what you're after. If you want both Parent and Child to see the same data (as an info and an info2, respectively), then data should itself be used polymorphically. For this example, I'll use a regular pointer for simplicity (and in turn, operator. will be replaced with operator->, when accessing data's members), but I would recommend looking into smart pointers such as std::unique_ptr to simplify the memory management.
class Parent
{
public:
struct info
{
int a;
// Chances are, it's going to be deleted through an info* no matter what it is. Therefore, virtual destructor.
virtual ~info() = default;
};
info* data; // Consider using a smart pointer here, like std::unique_ptr.
virtual void main(void);
virtual void output() const; // Just adding this for convenience.
// Default constructor now allows data to be supplied, or creates it if necessary.
Parent(info* dp = nullptr) : data(dp ? dp : new info) {}
// Correct destructor will always be called.
virtual ~Parent() { if(data) { delete data; } }
};
void Parent::main()
{
data->a =1;
}
We now remove the field Child::data, and instead have Child supply its desired data to Parent's constructor.
class Child: public Parent
{
public:
struct info2: public info
{
int b;
};
//info2 data;
virtual void main(void);
void output() const override; // Just adding this for convenience.
Child() : Parent(new info2) {}
};
Child will, when required, view data as an info2 instead of an info.
void Child::main(void)
{
Parent::main();
auto dataPtr = static_cast<info2*>(data); // In Child, we know data is an info2*.
dataPtr->b = 2;
// Just gonna move these to output(), for a cleaner illustration.
//std::cout << "Data->a: " << data->a << "\n";
//std::cout << "Data->b: " << dataPtr->b << "\n";
}
This will then cause data to work as desired, with Parent and Child both having the correct type.
void Parent::output() const {
std::cout << "Parent:\n";
std::cout << "> Data->a: " << data->a << "\n";
}
void Child::output() const /*override*/ {
std::cout << "Child as ";
Parent::output();
auto dataPtr = static_cast<info2*>(data);
std::cout << "Child:\n";
std::cout << "> Data->a: " << dataPtr->a << "\n";
std::cout << "> Data->b: " << dataPtr->b << "\n";
}
This will then perform as expected, as seen live on Coliru. Note that if you want to be able to, e.g., create a Child from a pre-existing Parent, you'll want to add a move constructor that can make an info2 from an info; you should consider following the Rule of Five, or using a smart pointer instead of a raw pointer. ;P
You have to use the below code:
void Child::main(void)
{
Parent::main();
data.b = 2;
std::cout << Parent::data.a << "\n";
std::cout << data.b << "\n";
}

C++ diamond problem - How to call base method only once

I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:
Creature
/ \
Swimmer Flier
\ /
Duck
Which corresponds to
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
Creature::print();
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
Creature::print();
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
void print()
{
Flier::print();
Swimmer::print();
std::cout << "I'm a duck" << std::endl;
}
};
Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-
I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck
I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).
Is there some built-in way to do this or do we need to resort to implementing one ourselves?
If so, how would you approach this?
The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.
I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.
Most likely this is a XY problem. But ... just don't call it twice.
#include <iostream>
class Creature
{
public:
virtual void identify()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a swimmer\n";
}
virtual void tell_ability()
{
std::cout << "I can swim\n";
}
};
class Flier : public virtual Creature
{
public:
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a flier\n";
}
virtual void tell_ability()
{
std::cout << "I can fly\n";
}
};
class Duck : public Flier, public Swimmer
{
public:
virtual void tell_ability() override
{
Flier::tell_ability();
Swimmer::tell_ability();
}
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a duck\n";
}
};
int main()
{
Creature c;
c.identify();
std::cout << "------------------\n";
Swimmer s;
s.identify();
std::cout << "------------------\n";
Flier f;
f.identify();
std::cout << "------------------\n";
Duck d;
d.identify();
std::cout << "------------------\n";
}
Output:
I'm a creature
------------------
I'm a creature
I can swim
I'm a swimmer
------------------
I'm a creature
I can fly
I'm a flier
------------------
I'm a creature
I can fly
I can swim
I'm a duck
------------------
We can let the base class keep track of the attributes:
#include <iostream>
#include <string>
#include <vector>
using namespace std::string_literals;
class Creature
{
public:
std::string const attribute{"I'm a creature"s};
std::vector<std::string> attributes{attribute};
virtual void print()
{
for (auto& i : attributes)
std::cout << i << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
Swimmer() { attributes.push_back(attribute); }
std::string const attribute{"I can swim"s};
};
class Flier : public virtual Creature
{
public:
Flier() { attributes.push_back(attribute); }
std::string const attribute{"I can fly"s};
};
class Duck : public Flier, public Swimmer
{
public:
Duck() { attributes.push_back(attribute); }
std::string const attribute{"I'm a duck"s};
};
int main()
{
Duck d;
d.print();
}
Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:
#include <iostream>
#include <functional>
#include <vector>
class Creature
{
public:
std::vector<std::function<void()>> print_functions{[this] {Creature::print_this(); }};
virtual void print_this()
{
std::cout << "I'm a creature" << std::endl;
}
void print()
{
for (auto& f : print_functions)
f();
}
};
class Swimmer : public virtual Creature
{
public:
Swimmer() { print_functions.push_back([this] {Swimmer::print_this(); }); }
void print_this()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
Flier() { print_functions.push_back([this] {Flier::print_this(); }); }
void print_this()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
Duck() { print_functions.push_back([this] {Duck::print_this(); }); }
void print_this()
{
std::cout << "I'm a duck" << std::endl;
}
};
int main()
{
Duck d;
d.print();
}
An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.
struct CreaturePrinter {
CreaturePrinter() {
std::cout << "I'm a creature\n";
}
};
struct FlierPrinter: virtual CreaturePrinter ...
struct SwimmerPrinter: virtual CreaturePrinter ...
struct DuckPrinter: FlierPrinter, SwimmerPrinter ...
Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.
For maintainability you can make each printer class nested in its corresponding main class.
Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.
Your explicit calls to the print methods form the crux of the issue.
One way round this would be to drop the print calls, and replace them with say
void queue(std::set<std::string>& data)
and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.
You then implement the printing of the set in a single method in Creature.
If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.
If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
Creature::print();
detailPrint();
}
void detailPrint()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
Creature::print();
detailPrint();
}
void detailPrint()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
void print()
{
Creature::Print();
Flier::detailPrint();
Swimmer::detailPrint();
detailPrint();
}
void detailPrint()
{
std::cout << "I'm a duck" << std::endl;
}
};
Without details what is your actual problem is, it hard to come up with a better solution.
Use:
template<typename Base, typename Derived>
bool is_dominant_descendant(Derived * x) {
return std::abs(
std::distance(
static_cast<char*>(static_cast<void*>(x)),
static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
)
) <= sizeof(Derived);
};
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Walker : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can walk" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer, public Walker
{
public:
void print()
{
Walker::print();
Swimmer::print();
Flier::print();
std::cout << "I'm a duck" << std::endl;
}
};
And with Visual Studio 2015 the output is:
I'm a creature
I can walk
I can swim
I can fly
I'm a duck
But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.
You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:
class Swimmer : public virtual Creature
{
public:
// Virtually inherit from Creature::print and extend it by another line of code
void print() : virtual Creature::print()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
// Virtually inherit from Creature::print and extend it by another line of code
void print() : virtual Creature::print()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
// Inherit from both prints. As they were created using "virtual function inheritance",
// this will "mix" them just like in virtual class inheritance
void print() : Flier::print(), Swimmer::print()
{
std::cout << "I'm a duck" << std::endl;
}
};
So the answer to your question
Is there some built-in way to do this?
is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...

Is it possible to replace a parent class?

If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.

Overriding a grandparent's virtual method that was called in grandparent's constructor

I'm having trouble on my c++ code ..
class GrandParent {
public:
GrandParent()
{
printMe();
}
virtual void printMe()
{
std::cout << "GrandParent: printme" << std::endl;
}
}
class Parent : public GrandParent {
public:
Parent(){}
virtual void printMe()
{
std::cout << "Parent: printMe!" << std::endl;
}
}
class Child : public Parent {
public:
Child(){}
void printMe()
{
std::cout << "Child: printMe!" << std::endl;
}
}
int main()
{
Child *p = new Child();
delete p;
}
When I run this code, it prints "GrandParent: printMe".
my goal is to print "Child: printMe!". Is there something wrong in overriding printMe?
What you're trying to do isn't possible. At the time of GrandParent's constructor, the only part of the Child object that has been constructed and initialized is the GrandParent part - including the vtable. That is, when you call printMe(), the entry will be GrandParent's. It's only after Child gets constructed that the vtable entry for printMe() gets updated to point to Child::printMe.
Note that it's good that C++ works like this. If Child::printMe had been the one called, then you'd be calling a member function on a not-yet-constructed object. Nothing good can come of that.
Short answer: That's how C++ works.
When a virtual method is called from the constructor, not the method of the runtime class is used. Instead the method of the compile time class is used.
But there might be an escape using the Curiously Recurring Template Pattern as shown here:
#include <iostream>
template <class T>
class Base
{
protected:
Base()
{
T::printMe();
}
};
class GrandParent : Base<GrandParent>
{
public:
GrandParent()
: Base<GrandParent>()
{}
static void printMe()
{
std::cout << "GrandParent: printMe!" << std::endl;
}
};
class Parent : public GrandParent, public Base<Parent>
{
public:
Parent()
{}
static void printMe()
{
std::cout << "Parent: printMe!" << std::endl;
}
};
class Child : public Parent, public Base<Child>
{
public:
Child()
{}
static void printMe()
{
std::cout << "Child: printMe!" << std::endl;
}
};
int main()
{
GrandParent a;
std::cout << "..." << std::endl;
Parent b;
std::cout << "..." << std::endl;
Child c;
std::cout << "..." << std::endl;
}
Output:
GrandParent: printMe!
...
GrandParent: printMe!
Parent: printMe!
...
GrandParent: printMe!
Parent: printMe!
Child: printMe!
...
But yeah, then you have to deal with static methods and multiple inheritence.

Is there any automated way to implement post-constructor and pre-destructor virtual method calls?

Due to the well-known issues with calling virtual methods from inside constructors and destructors, I commonly end up with classes that need a final-setup method to be called just after their constructor, and a pre-teardown method to be called just before their destructor, like this:
MyObject * obj = new MyObject;
obj->Initialize(); // virtual method call, required after ctor for (obj) to run properly
[...]
obj->AboutToDelete(); // virtual method call, required before dtor for (obj) to clean up properly
delete obj;
This works, but it carries with it the risk that the caller will forget to call either or both of those methods at the appropriate times.
So the question is: Is there any way in C++ to get those methods to be called automatically, so the caller doesn't have to remember to do call them? (I'm guessing there isn't, but I thought I'd ask anyway just in case there is some clever way to do it)
While there is no automated way, you could force the users hand by denying users access to the destructor on that type and declaring a special delete method. In this method you could do the virtual calls you'd like. Creation can take a similar approach which a static factory method.
class MyObject {
...
public:
static MyObject* Create() {
MyObject* pObject = new MyObject();
pObject->Initialize();
return pObject;
}
Delete() {
this->AboutToDelete();
delete this;
}
private:
MyObject() { ... }
virtual ~MyObject() { ... }
};
Now it is not possible to call "delete obj;" unless the call site has access to MyObject private members.
The best I can think of is for you to implement your own smart pointer with a static Create method that news up an instance and calls Initialize, and in its destructor calls AboutToDelete and then delete.
I used a very carefully designed Create() factory method (static member of each class) to call a constructor and initializer pair in the same order as C# initializes types. It returned a shared_ptr to an instance of the type, guaranteeing a heap allocation. It proved reliable and consistent over time.
The trick: I generated my C++ class declarations from XML...
Except for JavedPar's idea for the pre-destruction method, there is no pre-made solution to easily do two-phase construction/destruction in C++. The most obvious way to do this is to follow the Most Common Answer To Problems In C++: "Add another layer of indirection."
You can wrap objects of this class hierarchy within another object. That object's constructors/destructor could then call these methods. Look into Couplien's letter-envelop idiom, for example, or use the smart pointer approach already suggested.
http://www.research.att.com/~bs/wrapper.pdf This paper from Stroustrup will solve your problem.
I tested this under VS 2008 and on UBUNTU against g++ compiler. It worked fine.
#include <iostream>
using namespace std;
template<class T>
class Wrap
{
typedef int (T::*Method)();
T* p;
Method _m;
public:
Wrap(T*pp, Method m): p(pp), _m(m) { (p->*_m)(); }
~Wrap() { delete p; }
};
class X
{
public:
typedef int (*Method)();
virtual int suffix()
{
cout << "X::suffix\n";
return 1;
}
virtual void prefix()
{
cout << "X::prefix\n";
}
X() { cout << "X created\n"; }
virtual ~X() { prefix(); cout << "X destroyed\n"; }
};
class Y : public X
{
public:
Y() : X() { cout << "Y created\n"; }
~Y() { prefix(); cout << "Y destroyed\n"; }
void prefix()
{
cout << "Y::prefix\n";
}
int suffix()
{
cout << "Y::suffix\n";
return 1;
}
};
int main()
{
Wrap<X> xx(new X, &X::suffix);
Wrap<X>yy(new Y, &X::suffix);
}
I was stuck with the same problem, and after a bit of research, I believe there is not any standard solution.
The suggestions that I liked most are the ones provided in the Aleksandrescu et al. book "C++ coding standards" in the item 49.
Quoting them (fair use), you have several options:
Just document it that you need a second method, as you did.
Have another internal state (a boolean) that flags if post-construction has taken place
Use virtual class semantics, in the sense that the constructor of the most-derived class decides which base class to use
Use a factory function.
See his book for details.
You can use static function template in the class. With private ctor/dtor.
Run on vs2015 community
class A {
protected:
A() {}
virtual ~A() {}
virtual void onNew() = 0;
virtual void onDelete() = 0;
public:
void destroy() {
onDelete();
delete this;
}
template <class T> static T* create() {
static_assert(std::is_base_of<A, T>::value, "T must be a descendant of A");
T* t = new T();
t->onNew();
return t;
}
};
class B: public A {
friend A;
protected:
B() {}
virtual ~B() {}
virtual void onNew() override {
}
virtual void onDelete() override {
}
};
int main() {
B* b;
b = A::create<B>();
b->destroy();
}
The main problem with adding post-constructors to C++ is that nobody has yet established how to deal with post-post-constructors, post-post-post-constructors, etc.
The underlying theory is that objects have invariants. This invariant is established by the constructor. Once it has been established, methods of that class can be called. With the introduction of designs that would require post-constructors, you are introducing situations in which class invariants do not become established once the constructor has run. Therefore, it would be equally unsafe to allow calls to virtual functions from post-constructors, and you immediately lose the one apparent benefit they seemed to have.
As your example shows (probably without you realizing), they're not needed:
MyObject * obj = new MyObject;
obj->Initialize(); // virtual method call, required after ctor for (obj) to run properly
obj->AboutToDelete(); // virtual method call, required before dtor for (obj) to clean up properly
delete obj;
Let's show why these methods are not needed. These two calls can invoke virtual functions from MyObject or one of its bases. However, MyObject::MyObject() can safely call those functions too. There is nothing that happens after MyObject::MyObject() returns which would make obj->Initialize() safe. So either obj->Initialize() is wrong or its call can be moved to MyObject::MyObject(). The same logic applies in reverse to obj->AboutToDelete(). The most derived destructor will run first and it can still call all virtual functions, including AboutToDelete().
I had the same problem for construction. This is my solution using C++14.
The idea is to declare an instance of the class Call in the same (or quite close) scope than the declaration of the final object, letting the destructor call the post-creation script.
# include <iostream>
# include <cassert>
# include <memory>
# include <typeinfo>
class A;
// This non-template class stores an access to the instance
// on which a procedure must be called after construction
// The functions are defined after A in order to avoid a loop
class Call
{
protected:
A* a;
public:
Call();
virtual ~Call();
virtual void set(A& a_) = 0;
};
// In this class, the Source must be the final type created
template <typename Source>
class Call_ : public Call
{
static_assert(std::is_final<Source>::value, "");
public:
Call_() : Call() {}
virtual ~Call_() { assert(typeid(*this->a) == typeid(Source)); }
virtual void set(A& a_) { this->a = &a_; }
};
class A
{
protected:
A(Call& call) { std::cout << "Build A" << std::endl; call.set(*this); } // <----
public:
A(A const&) { std::cout << "Copy A" << std::endl; }
virtual ~A() { std::cout << "Delete A" << std::endl; }
virtual void actions_after_construction() = 0; // post-creation procedure
};
Call::Call() : a(nullptr)
{}
Call::~Call()
{
assert(this->a);
this->a->actions_after_construction();
}
class B : public A
{
protected:
B(Call& call) : A(call) { std::cout << "Build B" << std::endl; }
public:
B(B const& b) : A(b) { std::cout << "Copy B" << std::endl; }
virtual ~B() { std::cout << "Delete B" << std::endl; }
virtual void actions_after_construction() { std::cout << "actions by B" << std::endl; }
};
class C final : public B
{
private:
C(Call& call) : B(call) { std::cout << "Build C" << std::endl; }
public:
C(std::shared_ptr<Call> p_call = std::shared_ptr<Call>(new Call_<C>)) : C(*p_call) {}
C(C const& c) : B(c) { std::cout << "Copy C" << std::endl; }
virtual ~C() { std::cout << "Delete C" << std::endl; }
virtual void actions_after_construction() { std::cout << "actions by C" << std::endl; }
};
class D final : public B
{
private:
D(Call& call) : B(call) { std::cout << "Build D" << std::endl; }
public:
D(std::shared_ptr<Call> p_call = std::shared_ptr<Call>(new Call_<D>)) : D(*p_call) {}
D(D const& d) : B(d) { std::cout << "Copy D" << std::endl; }
virtual ~D() { std::cout << "Delete D" << std::endl; }
virtual void actions_after_construction() { std::cout << "actions by D" << std::endl; }
};
int main()
{
{ C c; }
{ D d; }
return 0;
}
Haven't seen the answer yet, but base classes are only one way to add code in a class hierarchy. You can also create classes designed to be added to the other side of the hierarchy:
template<typename Base>
class Derived : public Base {
// You'd need C++0x to solve the forwarding problem correctly.
Derived() : Base() {
Initialize();
}
template<typename T>
Derived(T const& t): Base(t) {
Initialize();
}
//etc
private:
Initialize();
};