when reading "Beyond the C++ Standard Library: An Introduction to Boost " ,I got a very interesting example:
class A
{
public:
virtual void sing()=0;
protected:
virtual ~A() {};
};
class B : public A
{
public:
virtual void sing( )
{
std::cout << "Do re mi fa so la"<<std::endl;;
}
};
and I do some testing:
int main()
{
//1
std::auto_ptr<A> a(new B); //will not compile ,error: ‘virtual A::~A()’ is protected
//2
A *pa = new B;
delete pa; //will not compile ,error: ‘virtual A::~A()’ is protected
delete (dynamic_cast<B*>(pa)); //ok
//3
boost::shared_ptr<A> a(new B);//ok
}
what I am very curious here is how ~shared_ptr works?
how it deduce the derived class B ?
Thanks advance for your help!
thanks all,
I write a simple sample about how ~shared_ptr works
class sp_counted_base
{
public:
virtual ~sp_counted_base(){}
};
template<typename T>
class sp_counted_base_impl : public sp_counted_base
{
public:
sp_counted_base_impl(T *t):t_(t){}
~sp_counted_base_impl(){delete t_;}
private:
T *t_;
};
class shared_count
{
public:
static int count_;
template<typename T>
shared_count(T *t):
t_(new sp_counted_base_impl<T>(t))
{
count_ ++;
}
void release()
{
--count_;
if(0 == count_) delete t_;
}
~shared_count()
{
release();
}
private:
sp_counted_base *t_;
};
int shared_count::count_(0);
template<typename T>
class myautoptr
{
public:
template<typename Y>
myautoptr(Y* y):sc_(y),t_(y){}
~myautoptr(){ sc_.release();}
private:
shared_count sc_;
T *t_;
};
int main()
{
myautoptr<A> a(new B);
}
the key is:
template construct function
the resource not deleted in ~shared_ptr ,it is deleted by shared_count
Surprisingly, the key here is not boost::shared_ptr destructor but its constructor(s).
If you look into boost/shared_ptr.hpp, you will see that shared_ptr<T> does not 'simply' have a constructor expecting a T * but :
template<class Y>
explicit shared_ptr( Y * p );
In //3 when you construct a boost::shared_ptr from a B *, no conversion to A * takes place, and the shared_ptr internals are built with the actual B type. Upon destruction of the object, deletion occurs on a B pointer (not through a base class pointer).
The shared_ptr class template has a member of class type shared_count, which in turn has a member of type pointer to class sp_counted_base. The constructor template for class shared_count assigns a pointer to an instance of the class template sp_counted_impl_p to this member which is templated by the type of the constructor argument, not by the shared_ptr::value_type. sp_counted_base has a pure virtual member function dispose which is overwritten by sp_counted_impl_p. Because sp_counted_impl_p knows the type B in your example, it can delete it without access to the base class destructor, and because it uses virtual dispatch, the type is determined at runtime. This method requires a combination of parametric and subtype polymorphism.
Related
class Base
{
public:
virtual void f()
{
g();
}
virtual void g()
{
cout<<"base";
}
};
class Derived : public Base
{
public:
virtual void f()
{
Base::f();
}
virtual void g()
{
cout<<"derived";
}
};
int main()
{
Base *pBase = new Derived;
pBase->f();
return 0;
}
In this program I have kept both derived and base class functions as virtual. Is it possible call virtual functions of derived class through base class pointer and base class functions are not virtual.
Thanks in advance..
assuming functions in base class are not virtual
This can be achieved via type erasure. But there are caveats.
Your "base" class should decide between the two:
Being a view class (can't be called delete on or created by itself)
Being a resource owning class (implemented similar to 1, but stores a smart pointer).
Here is an example for case 1: https://godbolt.org/z/v5rTv3ac7
template <typename>
struct tag{};
class base
{
public:
base() = delete;
template <typename Derived>
explicit base(tag<Derived> t)
: _vTable(make_v_table(t))
{}
int foo() const { return _vTable.foo(*this); }
protected:
~base() = default;
private:
struct v_table
{
virtual int foo(const base &b) const = 0;
protected:
~v_table() = default;
};
template <typename Derived>
static const v_table& make_v_table(tag<Derived>){
struct : v_table
{
int foo(const base &b) const {
return static_cast<const Derived&>(b).foo();
}
} static const _vTable{};
return _vTable;
}
private:
const v_table& _vTable;
};
class derived : public base
{
public:
explicit derived()
: base(tag<derived>{})
{}
int foo() const { return 815; }
};
// example
#include <iostream>
int main(){
derived d{};
const base& b = d;
std::cout << b.foo() << '\n';
}
Take notice, that you can only take a pointer or a reference (cv-qualified) to a base class. The base class can't be created on its own.
Also tag<T> is needed to call a templated constructor.
DO NOT CALL DERIVED METHODS IN THE BASE CONSTRUCTOR OR DESTRUCTOR
Simple answer is no, if the function you are calling is not virtual. The Compiler would have no Idea that you are trying to call a function from the Derived Class, and won't make and I'm paraphrasing here since I do not know the proper term for,"Won't make proper entries in the Virtual Table".
class Base
{
public:
void f()
{
std::cout<<"Base f() Called\n";
g();
}
virtual void g()
{
std::cout<<"Base g()\n";
}
virtual ~Base(){std::cout<<"Base Destroyed\n";}
};
class Derived : public Base
{
public:
void f()
{
g();
}
virtual void g()
{
std::cout<<"Derived g()\n";
}
~Derived(){std::cout<<"Derived Destroyed\n";}
};
int main()
{
Derived* D1 = new Derived();
Base* B1 = D1;
B1->f();
delete B1;
return 0;
}
Have a look at the following code, I have not declared Base::f() as virtual,calling B1->f() calls the Base Method, but the base method calls a virtual function Base::g() and this allows the "Derived" method be called.
Have a look at this thread or this blogpost to understand Virtual Tables.
(1) and you must ALWAYS declare the destructor of a base class virtual when destroying Derived Object through a Base Pointer, else the resources used by the Derived Object will never get destroyed and it's memory will leak until the program closes.
Don't Take my word as gospel, I am simply passing on knowledge I have acquired from first hand experience, Except for (1), specially if you are not using smart pointers
I have the following class:
class Base {
public:
Base() = default;
virtual ~Base() {};
}
And, let's say I have a unique_ptr to this class, aka:
using BasePtr = std::unique_ptr<Base>;
Now, let's assume I have a template class that inherits from the base class.
template <typename T>
class Derived : public Base {
public:
Derived() = default;
Derived(const T x) : some_variable(x) {};
~Derived() override {};
void hello() { std::cout << some_variable << std::endl; }
private:
T some_variable;
}
For arguments sake, let's say I have a factory method that creates a unique_ptr to some new instance, such as:
template <typename T>
auto make_class(const T& x) -> BasePtr {
return std::unique_ptr<Derived<T> >(new Derived<T>(x));
}
If I try to build this:
int main() {
auto ptr = make_class<int>(5);
if (ptr) {
ptr->hello();
}
return 0;
}
With C++11, this results in a compile error (saying that Base does not have a hello() method), because it seems that the actual instance stored in the unique_ptr is a Base, not a Derived.
Based on my understanding (at least if Derived wasn't templated), this should not be an issue. What's happening here?
You function make_class returns a BasePtr:
auto make_class(const T& x) -> BasePtr
Then in your main function you say:
auto ptr = make_class(5);
that is, ptr is a BasePtr. The function cannot know that the pointer actually points to a derived class. For this reason, there is no hello() function that could be invoked.
I have a base class MyBase that contains a pure virtual function:
void PrintStartMessage() = 0
I want each derived class to call it in their constructor
then I put it in base class(MyBase) constructor
class MyBase
{
public:
virtual void PrintStartMessage() =0;
MyBase()
{
PrintStartMessage();
}
};
class Derived:public MyBase
{
public:
void PrintStartMessage(){
}
};
void main()
{
Derived derived;
}
but I get a linker error.
this is error message :
1>------ Build started: Project: s1, Configuration: Debug Win32 ------
1>Compiling...
1>s1.cpp
1>Linking...
1>s1.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall MyBase::PrintStartMessage(void)" (?PrintStartMessage#MyBase##UAEXXZ) referenced in function "public: __thiscall MyBase::MyBase(void)" (??0MyBase##QAE#XZ)
1>C:\Users\Shmuelian\Documents\Visual Studio 2008\Projects\s1\Debug\s1.exe : fatal error LNK1120: 1 unresolved externals
1>s1 - 2 error(s), 0 warning(s)
I want force to all derived classes to...
A- implement it
B- call it in their constructor
How I must do it?
There are many articles that explain why you should never call virtual functions in constructor and destructor in C++. Take a look here and here for details what happens behind the scene during such calls.
In short, objects are constructed from the base up to the derived. So when you try to call a virtual function from the base class constructor, overriding from derived classes hasn't yet happened because the derived constructors haven't been called yet.
Trying to call a pure abstract method from a derived while that object is still being constructed is unsafe. It's like trying to fill gas into a car but that car is still on the assembly line and the gas tank hasn't been put in yet.
The closest you can get to doing something like that is to fully construct your object first and then calling the method after:
template <typename T>
T construct_and_print()
{
T obj;
obj.PrintStartMessage();
return obj;
}
int main()
{
Derived derived = construct_and_print<Derived>();
}
You can't do it the way you imagine because you cannot call derived virtual functions from within the base class constructor—the object is not yet of the derived type. But you don't need to do this.
Calling PrintStartMessage after MyBase construction
Let's assume that you want to do something like this:
class MyBase {
public:
virtual void PrintStartMessage() = 0;
MyBase() {
printf("Doing MyBase initialization...\n");
PrintStartMessage(); // ⚠ UB: pure virtual function call ⚠
}
};
class Derived : public MyBase {
public:
virtual void PrintStartMessage() { printf("Starting Derived!\n"); }
};
That is, the desired output is:
Doing MyBase initialization...
Starting Derived!
But this is exactly what constructors are for! Just scrap the virtual function and make the constructor of Derived do the job:
class MyBase {
public:
MyBase() { printf("Doing MyBase initialization...\n"); }
};
class Derived : public MyBase {
public:
Derived() { printf("Starting Derived!\n"); }
};
The output is, well, what we would expect:
Doing MyBase initialization...
Starting Derived!
This doesn't enforce the derived classes to explicitly implement the PrintStartMessage functionality though. But on the other hand, think twice whether it is at all necessary, as they otherwise can always provide an empty implementation anyway.
Calling PrintStartMessage before MyBase construction
As said above, if you want to call PrintStartMessage before the Derived has been constructed, you cannot accomplish this because there is no yet a Derived object for PrintStartMessage to be called upon. It would make no sense to require PrintStartMessage to be a non-static member because it would have no access to any of the Derived data members.
A static function with factory function
Alternatively we can make it a static member like so:
class MyBase {
public:
MyBase() {
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase {
public:
static void PrintStartMessage() { printf("Derived specific message.\n"); }
};
A natural question arises of how it will be called?
There are two solution I can see: one is similar to that of #greatwolf, where you have to call it manually. But now, since it is a static member, you can call it before an instance of MyBase has been constructed:
template<class T>
T print_and_construct() {
T::PrintStartMessage();
return T();
}
int main() {
Derived derived = print_and_construct<Derived>();
}
The output will be
Derived specific message.
Doing MyBase initialization...
This approach does force all derived classes to implement PrintStartMessage. Unfortunately it's only true when we construct them with our factory function... which is a huge downside of this solution.
The second solution is to resort to the Curiously Recurring Template Pattern (CRTP). By telling MyBase the complete object type at compile time it can do the call from within the constructor:
template<class T>
class MyBase {
public:
MyBase() {
T::PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
static void PrintStartMessage() { printf("Derived specific message.\n"); }
};
The output is as expected, without the need of using a dedicated factory function.
Accessing MyBase from within PrintStartMessage with CRTP
While MyBase is being executed, its already OK to access its members. We can make PrintStartMessage be able to access the MyBase that has called it:
template<class T>
class MyBase {
public:
MyBase() {
T::PrintStartMessage(this);
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
static void PrintStartMessage(MyBase<Derived> *p) {
// We can access p here
printf("Derived specific message.\n");
}
};
The following is also valid and very frequently used, albeit a bit dangerous:
template<class T>
class MyBase {
public:
MyBase() {
static_cast<T*>(this)->PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
void PrintStartMessage() {
// We can access *this member functions here, but only those from MyBase
// or those of Derived who follow this same restriction. I.e. no
// Derived data members access as they have not yet been constructed.
printf("Derived specific message.\n");
}
};
No templates solution—redesign
Yet another option is to redesign your code a little. IMO this one is actually the preferred solution if you absolutely have to call an overridden PrintStartMessage from within MyBase construction.
This proposal is to separate Derived from MyBase, as follows:
class ICanPrintStartMessage {
public:
virtual ~ICanPrintStartMessage() {}
virtual void PrintStartMessage() = 0;
};
class MyBase {
public:
MyBase(ICanPrintStartMessage *p) : _p(p) {
_p->PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
ICanPrintStartMessage *_p;
};
class Derived : public ICanPrintStartMessage {
public:
virtual void PrintStartMessage() { printf("Starting Derived!!!\n"); }
};
You initialize MyBase as follows:
int main() {
Derived d;
MyBase b(&d);
}
You shouldn't call a virtual function in a constructor. Period. You'll have to find some workaround, like making PrintStartMessage non-virtual and putting the call explicitly in every constructor.
If PrintStartMessage() was not a pure virtual function but a normal virtual function, the compiler would not complain about it. However you would still have to figure out why the derived version of PrintStartMessage() is not being called.
Since the derived class calls the base class's constructor before its own constructor, the derived class behaves like the base class and therefore calls the base class's function.
I know this is an old question, but I came across the same question while working on my program.
If your goal is to reduce code duplication by having the Base class handle the shared initialization code while requiring the Derived classes to specify the code unique to them in a pure virtual method, this is what I decided on.
#include <iostream>
class MyBase
{
public:
virtual void UniqueCode() = 0;
MyBase() {};
void init(MyBase & other)
{
std::cout << "Shared Code before the unique code" << std::endl;
other.UniqueCode();
std::cout << "Shared Code after the unique code" << std::endl << std::endl;
}
};
class FirstDerived : public MyBase
{
public:
FirstDerived() : MyBase() { init(*this); };
void UniqueCode()
{
std::cout << "Code Unique to First Derived Class" << std::endl;
}
private:
using MyBase::init;
};
class SecondDerived : public MyBase
{
public:
SecondDerived() : MyBase() { init(*this); };
void UniqueCode()
{
std::cout << "Code Unique to Second Derived Class" << std::endl;
}
private:
using MyBase::init;
};
int main()
{
FirstDerived first;
SecondDerived second;
}
The output is:
Shared Code before the unique code
Code Unique to First Derived Class
Shared Code after the unique code
Shared Code before the unique code
Code Unique to Second Derived Class
Shared Code after the unique code
Facing the same problem, I imaginated a (not perfect) solution. The idea is to provide a certificate to the base class that the pure virtual init function will be called after the construction.
class A
{
private:
static const int checkValue;
public:
A(int certificate);
A(const A& a);
virtual ~A();
virtual void init() = 0;
public:
template <typename T> static T create();
template <typeneme T> static T* create_p();
template <typename T, typename U1> static T create(const U1& u1);
template <typename T, typename U1> static T* create_p(const U1& u1);
//... all the required possibilities can be generated by prepro loops
};
const int A::checkValue = 159736482; // or any random value
A::A(int certificate)
{
assert(certificate == A::checkValue);
}
A::A(const A& a)
{}
A::~A()
{}
template <typename T>
T A::create()
{
T t(A::checkValue);
t.init();
return t;
}
template <typename T>
T* A::create_p()
{
T* t = new T(A::checkValue);
t->init();
return t;
}
template <typename T, typename U1>
T A::create(const U1& u1)
{
T t(A::checkValue, u1);
t.init();
return t;
}
template <typename T, typename U1>
T* A::create_p(const U1& u1)
{
T* t = new T(A::checkValue, u1);
t->init();
return t;
}
class B : public A
{
public:
B(int certificate);
B(const B& b);
virtual ~B();
virtual void init();
};
B::B(int certificate) :
A(certificate)
{}
B::B(const B& b) :
A(b)
{}
B::~B()
{}
void B::init()
{
std::cout << "call B::init()" << std::endl;
}
class C : public A
{
public:
C(int certificate, double x);
C(const C& c);
virtual ~C();
virtual void init();
private:
double x_;
};
C::C(int certificate, double x) :
A(certificate)
x_(x)
{}
C::C(const C& c) :
A(c)
x_(c.x_)
{}
C::~C()
{}
void C::init()
{
std::cout << "call C::init()" << std::endl;
}
Then, the user of the class can't construct an instance without giving the certificate, but the certificate can only be produced by the creation functions:
B b = create<B>(); // B::init is called
C c = create<C,double>(3.1415926535); // C::init is called
Moreover, the user can't create new classes inheriting from A B or C without implementing the certificate transmission in the constructor. Then, the base class A has the warranty that init will be called after construction.
I can offer a work around / "companion" to your abstract base class using MACROS rather than templates, or staying purely within the "natural" constraints of the language.
Create a base class with an init function e.g.:
class BaseClass
{
public:
BaseClass(){}
virtual ~BaseClass(){}
virtual void virtualInit( const int i=0 )=0;
};
Then, add a macro for a constructor. Note there is no reason to not add multiple constructor definitions here, or have multiple macros to choose from.
#define BASECLASS_INT_CONSTRUCTOR( clazz ) \
clazz( const int i ) \
{ \
virtualInit( i ); \
}
Finally, add the macro to your derivation:
class DervivedClass : public BaseClass
{
public:
DervivedClass();
BASECLASS_INT_CONSTRUCTOR( DervivedClass )
virtual ~DervivedClass();
void virtualInit( const int i=0 )
{
x_=i;
}
int x_;
};
Long story short, what I want here is to declare a templated type in a base class and be able to access that type A<T> such that the base class B contains it and the derived class C is able to access it as C::A<T>. I did try declaring an int inside of class B and that can be accessed from the derived C class as C::int, here's the error!
||In constructor ‘D::D()’:|
|74|error: no match for ‘operator=’ (operand types are ‘A<C*>’ and ‘A<B*>’)|
|4|note: candidate: A<C*>& A<C*>::operator=(const A<C*>&)|
|4|note: no known conversion for argument 1 from ‘A<B*>’ to ‘const A<C*>&’|
And this is the code that does compile ( comment A<B*> i; and uncomment A<C*> i; to get the error).
#include <iostream>
//class with a template parameter
template <class a>
class A
{
private:
int somevalue;
public:
A(){}
~A(){}
void print()
{
std::cout<<somevalue<<std::endl;
}
};
//1. could forward declare
class C;
class B
{
protected:
A<B*> i;
//2. and then use
//A<C*> i;
public:
B(){}
~B(){}
A<B*> get()
{
return i;
}
/*
//3. use this return instead
A<C*> get()
{
return i;
}
*/
};
//specialization of B that uses B's methods variables
class C : public B
{
protected:
public:
C(){}
virtual ~C(){}
void method()
{
B::i.print();
}
};
//class D that inherits the specialization of C
class D : public C
{
private:
A<B*> i;//works
//4. but I want the inherited type to work like
//A<C*> i;// so that the type C* is interpreted as B*
public:
D()
{
this->i = C::i;
}
~D(){}
};
///////////////////////////////////////////////////////////////////////
int main()
{
D* d = new D();
delete d;
return 0;
}
But okay what if we tried this std::list<template parameter> LIST and then plug that in? That's the problem A<T> is std::list.
As far as I understand your issue now you seem to have a std::list<Base *> (renamed B to Base for clarity) and want to fill an std::list<Concrete*> (renamed C to Concrete, it's derived from Base) with it.
For that you need to iterate over the Base* pointers, checking for each whether it can be downcast to a Concrete* and if so adding it to the std::list<Concrete*>. You need to think about what to do if the downcast fails, too.
For all of this to work your Base needs to be a polymorphic base class, that is it must contain a virtual member function (don't forget to make the destructor virtual). Also note that this sounds like a catastrophe waiting to happen in terms of managing ownership of those pointers.
template<typename Base, typename Concrete>
std::list<Concrete*> downcast_list (std::list<Base*> const & bases) {
std::list<Concrete*> result;
for (auto const base_ptr : bases) {
Concrete * concrete_ptr = dynamic_cast<Concrete*>(base_ptr);
if (concrete_ptr != nullptr) {
result.push_back(concrete_ptr);
} else {
// Error or ignore?
}
}
return result;
}
Note: a more idiomatic version of this would use iterators.
I found the pattern to my problem, it's actually really simple and it serves as the base for encapsulating a class type a (which is a template parameter to be passed around, try looking at my question as a reference to class a). The pattern is shown below, it's generally what I wanted. I found it on this webpage Using Inheritance Between Templates chapter 7.5 from the book entitled OBJECT-ORIENTED
SOFTWARE DESIGN
and CONSTRUCTION
with C++ by Dennis Kafura. I'll copy it below the edited code for the sake of future reference in case anyone else needs it.
template <class a>
class B
{
private:
public:
B();
~B();
};
template <class a>
class C : public B<a>
{
public:
C();
~C();
};
This is the code it was adapted from.
template <class QueueItem> class Queue
{
private:
QueueItem buffer[100];
int head, tail, count;
public:
Queue();
void Insert(QueueItem item);
QueueItem Remove();
~Queue();
};
template <class QueueItem> class InspectableQueue : public Queue<QueueItem>
{
public:
InspectableQueue();
QueueItem Inspect(); // return without removing the first element
~InspectableQueue();
};
Try changing this:
#include <iostream>
//class with a template parameter
template <class a>
class A {
private:
int somevalue;
public:
A(){}
~A(){}
void print() {
std::cout<<somevalue<<std::endl;
}
};
//1. could forward declare
class C;
class B {
protected:
A<B*> i;
//2. and then use
//A<C*> i;
public:
B(){}
~B(){}
A<B*> get() {
return i;
}
/*/3. use this return instead
A<C*> get() {
return i;
} */
};
//specialization of B that uses B's methods variables
class C : public B {
protected:
public:
C(){}
virtual ~C(){}
void method() {
B::i.print();
}
};
//class D that inherits the specialization of C
class D : public C {
private:
A<B*> i;//works
//4. but I want the inherited type to work like
//A<C*> i;// so that the type C* is interpreted as B*
public:
D() {
this->i = C::i;
}
~D(){}
};
int main() {
D* d = new D();
delete d;
return 0;
}
To Something Like This:
#include <iostream>
//class with a template parameter
template <typename T>
class Foo {
private:
T value_;
public:
Foo(){} // Default
Foo( T value ) : value_(value) {}
~Foo(){}
void print() {
std::cout<< value_ << std::endl;
}
};
class Derived;
class Base {
protected:
Foo<Base*> foo_;
Base(){} // Default;
virtual ~Base(){}
// Overload This Function
template<typename T = Base>
/*virtual*/ Foo<T*> get();
/*virtual*/ Foo<Base*> get() { return this->foo_; }
/*virtual*/ Foo<Derived*> get();
};
class Derived : Base {
public:
Derived() {}
virtual ~Derived() {}
void func() {
Base::foo_.print();
}
void Foo<Derived*> get() override { return this->foo_; }
};
And this is as about as far as I could get trying to answering your question...
There are objects that you are not using in your code
There are methods that aren't being called.
It is kind of hard to understand the direction/indirection
of what you mean to do with the inheritance tree.
You are inheriting from a base class without a virtual destructor
And probably a few other things that I can not think of off the top of my head right now.
I'd be more than willing to try and help you out; but this is as far as I can go with what you currently are showing.
EDIT -- I made changes to the base & derived classes and removed the virtual keyword to the overloaded function template declarations - definitions belonging to those classes.
I have a base class MyBase that contains a pure virtual function:
void PrintStartMessage() = 0
I want each derived class to call it in their constructor
then I put it in base class(MyBase) constructor
class MyBase
{
public:
virtual void PrintStartMessage() =0;
MyBase()
{
PrintStartMessage();
}
};
class Derived:public MyBase
{
public:
void PrintStartMessage(){
}
};
void main()
{
Derived derived;
}
but I get a linker error.
this is error message :
1>------ Build started: Project: s1, Configuration: Debug Win32 ------
1>Compiling...
1>s1.cpp
1>Linking...
1>s1.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall MyBase::PrintStartMessage(void)" (?PrintStartMessage#MyBase##UAEXXZ) referenced in function "public: __thiscall MyBase::MyBase(void)" (??0MyBase##QAE#XZ)
1>C:\Users\Shmuelian\Documents\Visual Studio 2008\Projects\s1\Debug\s1.exe : fatal error LNK1120: 1 unresolved externals
1>s1 - 2 error(s), 0 warning(s)
I want force to all derived classes to...
A- implement it
B- call it in their constructor
How I must do it?
There are many articles that explain why you should never call virtual functions in constructor and destructor in C++. Take a look here and here for details what happens behind the scene during such calls.
In short, objects are constructed from the base up to the derived. So when you try to call a virtual function from the base class constructor, overriding from derived classes hasn't yet happened because the derived constructors haven't been called yet.
Trying to call a pure abstract method from a derived while that object is still being constructed is unsafe. It's like trying to fill gas into a car but that car is still on the assembly line and the gas tank hasn't been put in yet.
The closest you can get to doing something like that is to fully construct your object first and then calling the method after:
template <typename T>
T construct_and_print()
{
T obj;
obj.PrintStartMessage();
return obj;
}
int main()
{
Derived derived = construct_and_print<Derived>();
}
You can't do it the way you imagine because you cannot call derived virtual functions from within the base class constructor—the object is not yet of the derived type. But you don't need to do this.
Calling PrintStartMessage after MyBase construction
Let's assume that you want to do something like this:
class MyBase {
public:
virtual void PrintStartMessage() = 0;
MyBase() {
printf("Doing MyBase initialization...\n");
PrintStartMessage(); // ⚠ UB: pure virtual function call ⚠
}
};
class Derived : public MyBase {
public:
virtual void PrintStartMessage() { printf("Starting Derived!\n"); }
};
That is, the desired output is:
Doing MyBase initialization...
Starting Derived!
But this is exactly what constructors are for! Just scrap the virtual function and make the constructor of Derived do the job:
class MyBase {
public:
MyBase() { printf("Doing MyBase initialization...\n"); }
};
class Derived : public MyBase {
public:
Derived() { printf("Starting Derived!\n"); }
};
The output is, well, what we would expect:
Doing MyBase initialization...
Starting Derived!
This doesn't enforce the derived classes to explicitly implement the PrintStartMessage functionality though. But on the other hand, think twice whether it is at all necessary, as they otherwise can always provide an empty implementation anyway.
Calling PrintStartMessage before MyBase construction
As said above, if you want to call PrintStartMessage before the Derived has been constructed, you cannot accomplish this because there is no yet a Derived object for PrintStartMessage to be called upon. It would make no sense to require PrintStartMessage to be a non-static member because it would have no access to any of the Derived data members.
A static function with factory function
Alternatively we can make it a static member like so:
class MyBase {
public:
MyBase() {
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase {
public:
static void PrintStartMessage() { printf("Derived specific message.\n"); }
};
A natural question arises of how it will be called?
There are two solution I can see: one is similar to that of #greatwolf, where you have to call it manually. But now, since it is a static member, you can call it before an instance of MyBase has been constructed:
template<class T>
T print_and_construct() {
T::PrintStartMessage();
return T();
}
int main() {
Derived derived = print_and_construct<Derived>();
}
The output will be
Derived specific message.
Doing MyBase initialization...
This approach does force all derived classes to implement PrintStartMessage. Unfortunately it's only true when we construct them with our factory function... which is a huge downside of this solution.
The second solution is to resort to the Curiously Recurring Template Pattern (CRTP). By telling MyBase the complete object type at compile time it can do the call from within the constructor:
template<class T>
class MyBase {
public:
MyBase() {
T::PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
static void PrintStartMessage() { printf("Derived specific message.\n"); }
};
The output is as expected, without the need of using a dedicated factory function.
Accessing MyBase from within PrintStartMessage with CRTP
While MyBase is being executed, its already OK to access its members. We can make PrintStartMessage be able to access the MyBase that has called it:
template<class T>
class MyBase {
public:
MyBase() {
T::PrintStartMessage(this);
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
static void PrintStartMessage(MyBase<Derived> *p) {
// We can access p here
printf("Derived specific message.\n");
}
};
The following is also valid and very frequently used, albeit a bit dangerous:
template<class T>
class MyBase {
public:
MyBase() {
static_cast<T*>(this)->PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
void PrintStartMessage() {
// We can access *this member functions here, but only those from MyBase
// or those of Derived who follow this same restriction. I.e. no
// Derived data members access as they have not yet been constructed.
printf("Derived specific message.\n");
}
};
No templates solution—redesign
Yet another option is to redesign your code a little. IMO this one is actually the preferred solution if you absolutely have to call an overridden PrintStartMessage from within MyBase construction.
This proposal is to separate Derived from MyBase, as follows:
class ICanPrintStartMessage {
public:
virtual ~ICanPrintStartMessage() {}
virtual void PrintStartMessage() = 0;
};
class MyBase {
public:
MyBase(ICanPrintStartMessage *p) : _p(p) {
_p->PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
ICanPrintStartMessage *_p;
};
class Derived : public ICanPrintStartMessage {
public:
virtual void PrintStartMessage() { printf("Starting Derived!!!\n"); }
};
You initialize MyBase as follows:
int main() {
Derived d;
MyBase b(&d);
}
You shouldn't call a virtual function in a constructor. Period. You'll have to find some workaround, like making PrintStartMessage non-virtual and putting the call explicitly in every constructor.
If PrintStartMessage() was not a pure virtual function but a normal virtual function, the compiler would not complain about it. However you would still have to figure out why the derived version of PrintStartMessage() is not being called.
Since the derived class calls the base class's constructor before its own constructor, the derived class behaves like the base class and therefore calls the base class's function.
I know this is an old question, but I came across the same question while working on my program.
If your goal is to reduce code duplication by having the Base class handle the shared initialization code while requiring the Derived classes to specify the code unique to them in a pure virtual method, this is what I decided on.
#include <iostream>
class MyBase
{
public:
virtual void UniqueCode() = 0;
MyBase() {};
void init(MyBase & other)
{
std::cout << "Shared Code before the unique code" << std::endl;
other.UniqueCode();
std::cout << "Shared Code after the unique code" << std::endl << std::endl;
}
};
class FirstDerived : public MyBase
{
public:
FirstDerived() : MyBase() { init(*this); };
void UniqueCode()
{
std::cout << "Code Unique to First Derived Class" << std::endl;
}
private:
using MyBase::init;
};
class SecondDerived : public MyBase
{
public:
SecondDerived() : MyBase() { init(*this); };
void UniqueCode()
{
std::cout << "Code Unique to Second Derived Class" << std::endl;
}
private:
using MyBase::init;
};
int main()
{
FirstDerived first;
SecondDerived second;
}
The output is:
Shared Code before the unique code
Code Unique to First Derived Class
Shared Code after the unique code
Shared Code before the unique code
Code Unique to Second Derived Class
Shared Code after the unique code
Facing the same problem, I imaginated a (not perfect) solution. The idea is to provide a certificate to the base class that the pure virtual init function will be called after the construction.
class A
{
private:
static const int checkValue;
public:
A(int certificate);
A(const A& a);
virtual ~A();
virtual void init() = 0;
public:
template <typename T> static T create();
template <typeneme T> static T* create_p();
template <typename T, typename U1> static T create(const U1& u1);
template <typename T, typename U1> static T* create_p(const U1& u1);
//... all the required possibilities can be generated by prepro loops
};
const int A::checkValue = 159736482; // or any random value
A::A(int certificate)
{
assert(certificate == A::checkValue);
}
A::A(const A& a)
{}
A::~A()
{}
template <typename T>
T A::create()
{
T t(A::checkValue);
t.init();
return t;
}
template <typename T>
T* A::create_p()
{
T* t = new T(A::checkValue);
t->init();
return t;
}
template <typename T, typename U1>
T A::create(const U1& u1)
{
T t(A::checkValue, u1);
t.init();
return t;
}
template <typename T, typename U1>
T* A::create_p(const U1& u1)
{
T* t = new T(A::checkValue, u1);
t->init();
return t;
}
class B : public A
{
public:
B(int certificate);
B(const B& b);
virtual ~B();
virtual void init();
};
B::B(int certificate) :
A(certificate)
{}
B::B(const B& b) :
A(b)
{}
B::~B()
{}
void B::init()
{
std::cout << "call B::init()" << std::endl;
}
class C : public A
{
public:
C(int certificate, double x);
C(const C& c);
virtual ~C();
virtual void init();
private:
double x_;
};
C::C(int certificate, double x) :
A(certificate)
x_(x)
{}
C::C(const C& c) :
A(c)
x_(c.x_)
{}
C::~C()
{}
void C::init()
{
std::cout << "call C::init()" << std::endl;
}
Then, the user of the class can't construct an instance without giving the certificate, but the certificate can only be produced by the creation functions:
B b = create<B>(); // B::init is called
C c = create<C,double>(3.1415926535); // C::init is called
Moreover, the user can't create new classes inheriting from A B or C without implementing the certificate transmission in the constructor. Then, the base class A has the warranty that init will be called after construction.
I can offer a work around / "companion" to your abstract base class using MACROS rather than templates, or staying purely within the "natural" constraints of the language.
Create a base class with an init function e.g.:
class BaseClass
{
public:
BaseClass(){}
virtual ~BaseClass(){}
virtual void virtualInit( const int i=0 )=0;
};
Then, add a macro for a constructor. Note there is no reason to not add multiple constructor definitions here, or have multiple macros to choose from.
#define BASECLASS_INT_CONSTRUCTOR( clazz ) \
clazz( const int i ) \
{ \
virtualInit( i ); \
}
Finally, add the macro to your derivation:
class DervivedClass : public BaseClass
{
public:
DervivedClass();
BASECLASS_INT_CONSTRUCTOR( DervivedClass )
virtual ~DervivedClass();
void virtualInit( const int i=0 )
{
x_=i;
}
int x_;
};