473,387 Members | 1,578 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Templates and virtual methods

Hello,

I've run into problems with defining a template, which inherits from a
base template and the usage of virtual methods in those. I want to
initialize a member variable depending on which template is created and
I tried to define a virtual method, that's called from the base
template ctor. Here's my example code:
#include <iostream>

using namespace std;

template<typename T>
class A
{
public:
A() { cout << "A()" << endl; c = create(); }
virtual ~A() {}

class C
{
public:
virtual ~C() {}
virtual void foo() { cout << "A::C:foo()" << endl; }
};

virtual C* create() { cout << "A::create()" << endl; return new C;
}
C* c;
};

template<typename T>
class B : public A<T>
{
public:
B() : A<T>() { cout << "B()" << endl; }
virtual ~B() {}

class C : virtual public A<T>::C
{
public:
virtual ~C() {}
virtual void foo() { cout << "B::C:foo()" << endl; }
};

virtual typename A<T>::C* create() { cout << "B::create()" << endl;
return new C; }
};

int main( int /*argc*/, char** /*argv*/ )
{
A<inta;
a.c->foo();

B<intb;
b.c->foo();
}
Compiling this with gcc 4.1.0 and running it gives me:
A()
A::create()
A::C:foo()
A()
A::create()
B()
A::C:foo()
I've expected, that B::create() will be called on instantiating B<int>.

Why is this not the case?
How do I achieve what I want, preferably by using virtual methods?

Regards,
Stefan

Aug 11 '06 #1
4 2319
Compiling this with gcc 4.1.0 and running it gives me:
A()
A::create()
A::C:foo()
A()
A::create()
B()
A::C:foo()
I've expected, that B::create() will be called on instantiating B<int>.
I don't have the answer for this, but here's a bit simpler example:

#include <iostream>

class Base
{
public:
Base()
{ this->fn(); }

virtual void fn()
{ std::cout<<"Base::fn()"<<std::endl; }
};

class Derived : public Base
{
public:
Derived() { }

void fn()
{ std::cout<<"Derived::fn()"<<std::endl; }
};

int main()
{
Base* b = new Derived;
return 0;
}

I guess somebody will come up with a quotation from the standard on why
this works this way..

Aug 11 '06 #2
Stefan Nikolaus schrieb:
Hello,

I've run into problems with defining a template, which inherits from a
base template and the usage of virtual methods in those. I want to
initialize a member variable depending on which template is created and
I tried to define a virtual method, that's called from the base
template ctor. Here's my example code:
#include <iostream>

using namespace std;

template<typename T>
class A
{
public:
A() { cout << "A()" << endl; c = create(); }
virtual ~A() {}

class C
{
public:
virtual ~C() {}
virtual void foo() { cout << "A::C:foo()" << endl; }
};

virtual C* create() { cout << "A::create()" << endl; return new C;
}
C* c;
};

template<typename T>
class B : public A<T>
{
public:
B() : A<T>() { cout << "B()" << endl; }
virtual ~B() {}

class C : virtual public A<T>::C
{
public:
virtual ~C() {}
virtual void foo() { cout << "B::C:foo()" << endl; }
};

virtual typename A<T>::C* create() { cout << "B::create()" << endl;
return new C; }
};

int main( int /*argc*/, char** /*argv*/ )
{
A<inta;
a.c->foo();

B<intb;
b.c->foo();
}
Compiling this with gcc 4.1.0 and running it gives me:
A()
A::create()
A::C:foo()
A()
A::create()
B()
A::C:foo()
I've expected, that B::create() will be called on instantiating B<int>.

Why is this not the case?
How do I achieve what I want, preferably by using virtual methods?
Read this:
http://www.artima.com/cppsource/nevercall.html

/S
--
Stefan Naewe
stefan_DOT_naewe_AT_atlas_DOT_de
Aug 11 '06 #3
Stefan Näwe wrote:
Read this:
http://www.artima.com/cppsource/nevercall.html
Oops, it's not even template related. It neither works with simple
class inheritance. :-(

Okay, thanks for the pointer.

Regards,
Stefan

Aug 11 '06 #4
"Stefan Nikolaus" <st*************@o2online.dewrote in message
news:11**********************@75g2000cwc.googlegro ups.com
Hello,

I've run into problems with defining a template, which inherits from a
base template and the usage of virtual methods in those. I want to
initialize a member variable depending on which template is created
and I tried to define a virtual method, that's called from the base
template ctor. Here's my example code:
#include <iostream>

using namespace std;

template<typename T>
class A
{
public:
A() { cout << "A()" << endl; c = create(); }
virtual ~A() {}

class C
{
public:
virtual ~C() {}
virtual void foo() { cout << "A::C:foo()" << endl; }
};

virtual C* create() { cout << "A::create()" << endl; return new C;
}
C* c;
};

template<typename T>
class B : public A<T>
{
public:
B() : A<T>() { cout << "B()" << endl; }
virtual ~B() {}

class C : virtual public A<T>::C
{
public:
virtual ~C() {}
virtual void foo() { cout << "B::C:foo()" << endl; }
};

virtual typename A<T>::C* create() { cout << "B::create()" << endl;
return new C; }
};

int main( int /*argc*/, char** /*argv*/ )
{
A<inta;
a.c->foo();

B<intb;
b.c->foo();
}
Compiling this with gcc 4.1.0 and running it gives me:
A()
A::create()
A::C:foo()
A()
A::create()
B()
A::C:foo()
I've expected, that B::create() will be called on instantiating
B<int>.
Why is this not the case?
create() is only called in A's constructor, so A::create() is called. Base
classes are always created before derived classes, so B doesn't exist at the
time A's constructor is called, making the virtual function call mechanism
inoperative.

http://www.parashift.com/c++-faq-lit....html#faq-23.5

Your code leaks memory, by the way, since the A::C object is never deleted.
How do I achieve what I want, preferably by using virtual methods?
As indicated above, you should not be using virtual methods in a
constructor.

Various approaches are described here

http://www.parashift.com/c++-faq-lit....html#faq-23.6

As an alterative, you can let the derived class call a constructor in the
base class that does the right initialisation. Try this:

#include <iostream>
#include <memory>
using namespace std;

template<typename T>
class A
{

// constructor to be called by derived class
protected:
// forward declaration
class C;
A(C * pDerivedC) : c(pDerivedC)
{
cout << "A(C * pDerivedC)" << endl;
}
public:
// constructor for an A object by itself
A() : c(create()) // calls A's create
{
cout << "A()" << endl;
}
virtual ~A() {}

class C
{
public:
virtual ~C() {}
virtual void foo() { cout << "A::C:foo()" << endl; }
};

C* create()
{
cout << "A::create()" << endl;
return new C;
}
auto_ptr<Cc;
};

template<typename T>
class B : virtual public A<T>
{
public:
B() : A<T>(create()) // calls B's create
{
cout << "B()" << endl;
}
virtual ~B() {}

class C : public A<T>::C
{
public:
virtual ~C() {}
virtual void foo() { cout << "B::C:foo()" << endl; }
};
C* create()
{
cout << "B::create()" << endl;
return new C;
}
};

int main( int /*argc*/, char** /*argv*/ )
{
A<inta;
a.c->foo();
B<intb;
b.c->foo();
}
--
John Carson
Aug 11 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Leslaw Bieniasz | last post by:
Cracow, 20.09.2004 Hi, I am posting this again, because my previous message dated 18.09. disappeared from the list (someone has cancelled it ? why ??). I have a problem with compiling the...
4
by: Martin | last post by:
Greetings I want to have virtual member functionality, but without my member functions being virtual:-) As of yet this is all just in my head cause I can't see a nice solution yet so lets...
8
by: puzzlecracker | last post by:
Can the template method be virtual and what are the consequences? Can the template inline functions be virtual and what are the consequences?
6
by: andreykuzmenko | last post by:
I'm thinking about using templates instead of virtual methods to boost the performance of my library. I would like to know if it is possible to do something like the following: template<class T>...
7
by: Jon Slaughter | last post by:
#pragma once #include <vector> class empty_class { }; template <int _I, int _J, class _element, class _property> class RDES_T {
32
by: Adrian Herscu | last post by:
Hi all, In which circumstances it is appropriate to declare methods as non-virtual? Thanx, Adrian.
3
by: Steven T. Hatton | last post by:
Has anybody here used explicit instantiation of templates? Has it worked well? Are there any issues to be aware of? -- NOUN:1. Money or property bequeathed to another by will. 2. Something...
6
by: Hunk | last post by:
Hi I have a question on usage of forward declarations of templates. While searching through this group , people suggested using forward declarations and typedefs for templates as // in...
5
by: Lars Hillebrand | last post by:
Hello, i discovered a weird behaviour if i use templates together with virtual inheritance and method over. I managed to reproduce my problem with a small example: // *********** <code...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.