I'm stuck with the following issue:
I've got a class Test with template T. When I create an object of this class, specializing with other common class, everything works fine. In the constructor of class Test there is one line of code which creates an object of the template class;
But when I try to instantiate this class (Test), specializing it with a subclass (SubDummy) of an abstract class (Dummy), I get an error: cannot instantiate an abstract class.
Example code (simplified to the purpose of this post):
class Dummy
{
private:
virtual void _nothing() = 0; // this makes the class abstract
};
class SubDummy : public Dummy
{
public:
SubDummy() :
Dummy()
{
}
};
template <class T>
class Test
{
public:
Test()
{
T t; // here the compiler reports the error
}
};
int main()
{
Test<SubDummy> x;
}
Classes containing pure virtual member functions simply cannot be instantiated. Since you didn't specify an override for _nothing in SubDummy, it is a pure virtual in this class as well. You must implement _nothing in SubDummy in order to make it work.
Sometimes, when debugging templates it's useful to think of what the class becomes when you instantiate it with the variables.
class TestWithSubDummy {
public:
TestWithSubDummy() {
SubDummy t;//the error
}
};
You are pretty obviously trying to instantiate a SubDummy (using the default constructor) at the error. But SubDummy is abstract, so we aren't allowed to instantiate it. Thus, the error.
Related
Suppose I want to implement abstract behavior in a base class that is inherited by all derived classes. For example, a function that clones an object, applies some modification to it and returns the cloned and modified object (e.g. transposition, duplication, etc). The following code uses an even simpler function that merely returns the object itself:
class Base
{
public:
virtual Base* yourself ()
{
return this;
}
};
class Derived : public Base
{
public:
...
};
void main()
{
Derived d;
auto result = d.yourself();
}
If I didn't miss something, result will be of type Base*, where the intention clearly is to get an object of type Derived*.
Is there a way to have yourself() return the intended value for all derived classes without overriding it in all places (actually the whole point of inheritance is to implement each behavior only once)?
This issue is fairly common, and you can get around it using templates. Something like this:
template <class T>
class Base
{
public:
virtual T* yourself ()
{
return dynamic_cast<T*>(this);
}
};
class Derived : public Base<Derived>
{
public:
...
};
It's called the Curiously recurring template pattern (CRTP)
Is it possible to declare a templated class in C++ along with the classes it inherits from? Basically I want to give the compiler a hint, that my templated class will always inherit another at declaration time.
Maybe some code will clear up why this is a problem for me:
template<typename T>
class GrandparentClass
{
public:
T grandparentMember;
};
//this needs to be only a declaration, since I do not want classes of ParentClass with random T
template<typename T>
class ParentClass : public GrandparentClass<T>
{
};
// this does not work:
//template<typename T>
//class ParentClass : public GrandparentClass<T>;
// this does not either, because then the child class cannot access the variable from the grandparent class
//template<typename T>
//class ParentClass;
template<>
class ParentClass<int> : public GrandparentClass<int>
{
public:
ParentClass()
{
grandparentMember = 5;
}
};
template <typename T>
class ChildClass : public ParentClass<T>
{
public:
void foo()
{
std::cout << grandparentMember << "\n";
}
};
Also, I cannot use C++ 11.
EDIT:
I found an easy way out of this:
template<typename T>
class ParentClass : public GrandparentClass<T>
{
public:
ParentClass() { ParentClass::CompilerError(); };
};
Just do not define CompilerError() method in the class and everything's fine.
A class declaration is only really useful for non-value variable declarations, like pointers and references. You can't access the class members or even instantiate it, though. Even if you knew that a declared class inherits from some other one, you still wouldn't necessarily be able to utilize that information in any way.
As such, it's only important for the compiler to know what the class inherits from once it learns its full definition.
After clarification in comments: if you want to prevent instantiation of a class template with some types, its definition is the place to do it. A simple static_assert inside the class body will do the trick; Boost.StaticAssert or older SFINAE tricks will do the job for pre-C++11 code.
If you are happy with delaying the error to link-time, rather than compile time, you can declare all the member functions of parent in parent.h, provide definitions in parent.cpp, and explicitly instantiate the finite list of classes that you want.
Parent.h
template<typename T>
class ParentClass : public GrandparentClass<T>
{
ParentClass();
};
class ParentClass<int>;
class ParentClass<long int>; // or whatever
Parent.cpp
template <typename T>
ParentClass::ParentClass() : grandparentMember(5) {}
How can i pass object that inherited from template as this to function
please see the GameObj::GameObj constructor
i try to pass the GameObj that is inheriting the BaseGameObject template
but its not valid
template<typename T>
class BaseGameObject
{
public:
BaseGameObject(){};
virtual ~BaseGameObject(){};
static T* create(IImageComponent* imageComponent)
{
}
protected:
IImageComponent* m_IImageComponent;
};
class GameObj :public BaseGameObject<GameObj>
{
public:
GameObj(IImageComponent* imageComponent);
virtual ~GameObj(){};
};
GameObj::GameObj(IImageComponent* imageComponent):m_IImageComponent(imageComponent)
{
m_IImageComponent->update(*this); //HERE IS THE PROBLEM IT ASK ME TO PASS TAMPLATE
}
class GameObjImageCompnent
{
public :
GameObjImageCompnent(const std::string &spritefilename);
virtual void update(BaseGameObject& baseGameObject);
private:
std::string m_spritefilename;
};
GameObjImageCompnent::GameObjImageCompnent(const std::string &spritefilename):
m_spritefilename(spritefilename)
{
;
}
void GameObjImageCompnent::update(BaseGameObject& baseGameObject)
{
baseGameObject.setInitWithSpriteFrameName(m_spritefilename);
}
this link doesn't work for me :
Passing template classes as arguments to methods
BaseGameObject is a template. GameObjImageCompnent::update has a declaration virtual void update(BaseGameObject& baseGameObject);. That's wrong because BaseGameObject is not a type but a template.
Maybe you should change that declaration to: virtual void update(BaseGameObject<GameObj>& baseGameObject);
If you need to be able to call that with different BaseGameObjects, you could make GameObjImageCompnent into a template as well:
template<class T>
class GameObjImageCompnent {
// ...
virtual void update(BaseGameObject<T>& baseGameObject);
If that's not an option, you probably need to inherit BaseGameObject from a non-template base class and and use that as your reference type. If a base class for BaseGameObject is not an option either, you need to rethink your design.
class IGameObject {
public:
virtual ~IGameObject() {}
// any other virtual functions that are needed
};
template<typename T>
class BaseGameObject: public IGameObject {
//...
class GameObjImageCompnent {
// ...
virtual void update(IGameObject& baseGameObject);
You seem to be using CRTP. See the pitfalls section:
One issue with static polymorphism is that without using a general base class like "Shape" from the above example, you cannot store your derived classes heterogeneously as each CRTP base class is a unique type. For this reason, it's likely that you'll want to inherit from a shared base class with a virtual destructor, like the example above.
I think that limitation also applies to passing objects of derived classes to a function through a heterogeneous reference.
i have a c++ class like the below one working at vc++ , but doesnt work anymore in linux gcc 4.7. And i have no idea how to make it work again.
test.h
template<typename a>
class test: public a
{
public:
void fun();
};
test.cpp
template<typename a>
void test<a>::fun()
{
template_class_method(); <-- this is a public method from template_class
}
template class test<template_class>;
template_class.h
class template_class {
public:
template_class();
virtual ~template_class();
void template_class_method();
};
template_class.cpp
#include "templateclass.h"
template_class::template_class() {
// TODO Auto-generated constructor stub
}
template_class::~template_class() {
// TODO Auto-generated destructor stub
}
void template_class::template_class_method() {
}
You need to qualify it with the base class name as:
a::template_class_method();
The qualification a:: is necessary because template_class_method exists in a. The C++ rule is that if the base is a class template or template argument, then all its members are not automatically visible to the derived classes. In order to help the compiler to find the member, you need to tell it to look for the member in the base class, for which you need to qualify the member which is of the form of base::member_function() or base::member_data.
In your case, since the base is a, and the member is template_class_method, so you have to write this:
a::template_class_method();
Note that such a base class is called dependent base class since it depends on the template argument.
I don't know why #Karthik T deleted the answer, but that answer was on the right path. You have several options
Use qualified name a::template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
a::template_class_method();
}
};
Use class member access syntax this->template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
this->template_class_method();
}
};
Make the base class method visible through using-declaration
template<typename a>
class test : public a
{
public:
using a::template_class_method;
void fun()
{
template_class_method();
}
};
Note that the first method will suppress the virtuality of template_class_method (in cases when it is virtual), so it should be used with caution. For this reason, method number 2 is preferred, since it preserves the natural behavior of template_class_method.
Your comment stating that this->template_class_method() "doesn't work" is unclear. It works without any problems. Moreover, as I said above, this is in general case a better option than using a qualified name.
In C++ I'm trying to make a simple state machine for a game, based on classes.
stateMan.setState<mainMenuState>();
I have a class with the declaration as:
class stateManager
{
...
template <class T>
void setState(void);
}
And the test code as:
template <class T>
void stateManager::setState<T>(void)
{
T* blah = new T;
delete blah;
}
And obviously this doesn't work since function template partial specialization ‘setState<T>’ is not allowed.
Would there be a better way to do this besides doing it non-OO?
The definition of the member function template should be this:
template <class T>
void stateManager::setState(void)
{
//...
}
That is, it should be simply setState instead of setState<T>. The latter syntax is used in function template specialization. Since T is a type parameter, the specialization would be considered as function partial template specialization which is not allowed.
Hard to say without the details, but you could do a base State class, and the different states inherit from it.
If you still want to use classes for this, you can see an interesting
example using boost.mpl.
Another option that avoids templates would be to define a pure virtual base class for your game states, and then pass references to different game-states to your function. For instance,
//pure virtual base class that will define the state interfaces
class base_state { /*...*/ };
//a derived state class
class mainMenuState : public base_state { /*...*/ };
class stateManager
{
//...
//you can pass any derived base_state to this function
void setState(base_state* state);
};