I'm having trouble passing a class DerivedObject (part of class DerivedClass derived from template class BaseClass) derived from BaseObject (part of template class BaseClass) as a template argument to template class BaseClass.
This way, both Base and Derived classes have the access to the object pool, that can contain derived objects. This sounds a bit confusing, so here is the example:
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
}
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<TDerivedObject*> m_objectPool;
};
The above is the base class implementation.
error C2065: 'DerivedObject' undeclared identifier
The above error is cause by the first line of the class definition bellow:
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
}
void foo()
{
// Method implementation
}
};
Is there a way to do this? If not, is there a better solution that would give me the same / similar functionality?
At this point
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
The compiler has not seen DerivedClass::DerivedObject so you get an undeclared identifier error. As they type has not been seen you cannot use it as a template parameter. You don't get one for DerivedClass as you already have declared DerivedClass as a class.
You could change you base class and have it store a std::vector<BaseObject*> in it and if you do that then you can change your code to:
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
};
void foo()
{
// Method implementation
}
};
Here is one way of doing something similar to what was requested:
#include <vector>
using std::vector;
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
public:
class BaseObject
{
// Class implementation
};
protected:
// void foo()
// {
// static_cast<TDerivedClass*>(this)->foo();
// }
// std::vector<TDerivedObject*> m_objectPool;
};
class DerivedClass;
class DerivedObject : public BaseClass<DerivedClass, DerivedObject>::BaseObject
{
// Class implementation
};
class DerivedClass : public BaseClass<DerivedClass, DerivedObject>
{
public:
void foo()
{
// Method implementation
}
};
From your example code, I get the impression that you want to provide different implementations for different base classes. Is there any special reason for using templates? If not, you could use classic polymorphism instead:
class BaseClass
{
class BaseObject {};
virtual ~BaseClass() {} // <- do not forget to provide virtual dtor!
virtual void foo() = 0;
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass
{
class DerivedObject : public BaseObject {/*...*/};
virtual void foo(){/*...*/}
};
Again, BaseObject would offer virtual or pure virtual functions - as you need.
One thing, however, you lose this way: the guarantee that in the vector there are always the objects of one specific BaseObject sub-type. If this matters for you, you could protect the pool and only allow to add new BaseObjects via DerivedClass. If this is not applicable, I might think up another solution from within BaseClass.
If you do not mind having the DerivedObject structure separately from the DerivedClass you may do something like that:
template <class T>
struct ObjectTypeTrait
{
static_assert(sizeof(T) == 0, "undefined trait");
};
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<typename ObjectTypeTrait<TDerivedClass>::obj*> m_objectPool;
};
class DerivedClass;
class DerivedObject
{
// Class implementation
};
template<>
struct ObjectTypeTrait<DerivedClass>
{
using obj = DerivedObject;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
void foo()
{
// Method implementation
}
};
I do not claim this to be very brilliant solution, but you can get the idea - using type traits or typedefs
Related
I have a naive C++ inheritance class question. I have one base class Base, two derived classes DerivedA and DerivedB and two other distinct classes A and B which share the names of some methods.
Ideally I would like to design methods in the base class that use the methods of A and B. My attempt is the following
#include <cstdio>
class A{
public :
A(){};
void speak(){printf("hello A\n");};
};
class B{
public :
B(){};
void speak(){printf("hello B\n");};
};
class Base{
public:
Base(){};
void method(){property.speak();}
A property;
};
class DerivedA : public Base{
public:
using Base::Base;
A property;
};
class DerivedB : public Base{
public:
using Base::Base;
B property;
};
int main(int argc, char *argv[]){
DerivedA da;
DerivedB db;
da.property.speak();
db.property.speak();
// Attempting to call the shared method on the two distinct properties
da.method();
db.method();
}
Could you point me to a better design ? I suspect I should use templates but I am not sure how.
There are several options with different advantages and disadvantages.
You can make the base class a template like this:
template<class Property>
class Base{
public:
Base(){};
void method(){property.speak();}
Property property;
};
class DerivedA : public Base<A>{
};
class DerivedB : public Base<B>{
};
It is clear and simple, but notice that DerivedA and DerivedB in this case have no common base class, so you can't, e.g. put pointers to them in the same container.
You can use polymorphism.
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;
};
class DerivedA : public Base{
public:
A property;
void method() override { property.speak(); }
};
class DerivedB : public Base{
public:
B property;
void method() override { property.speak(); }
};
This is a bit more complex, involves some code duplication and requires more resources (to store virtual table e.g.), but now the classes really have a common ancestor.
Combine templates and polymorphism
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;
};
template<class Property>
class Derived: public Base {
public:
Property property;
void method() override { property.speak(); }
};
using DerivedA = Derived<A>;
using DerivedB = Derived<B>;
This is actually option #2, but with no code duplication: we make the compiler generate code for us using templates.
Other options. There may be other more specialized options depending on your requirements.
I have a struct obj in my base class. I don't know how to access the data members of the struct through Derv1 class (Derived from the base class). I tried making both Base and Derv1 a friend of struct - it still tells me ' data member is private' (its private in Base only).
example :
struct A{
public :
int total;
//some stuff
};
class MyClass{ // [Base] class
private:
A var1;
};
class Derv1{
private:
//some stuff
public void display_var1(Derv1 x){
return x.var1.total;
} // trying to return the value of A.total
};
I hope this makes sense so that you can help me out ..
Thank You kindly,
First, you have to make sure that Derv derives from MyClass.
class Derv1 : public MyClass { ... };
and then, you will need to figure out the best way to display the variable.
My suggestion:
Create a virtual member function in the base class.
Override the function in the derived class.
Make sure to call the base class implementation in the derived class implementatin.
class MyClass { // [Base] class
public:
virtual void display() const
{
// Display var1 anyway you wish to.
}
private:
A var1;
};
class Derv1 : public MyClass {
public:
virtual void display() const
{
// Call the base class implementation first
MyClass::display():
// Display anything else that corresponds to this class
}
private:
//some stuff
};
i think you must extend your Derv1 class into the Base class:
class Derv1: public MyClass{
to inherit the members of the base class
I'll try to make my intentions clear since there may be more than one approach to this. To start, I have an abstract base class FooBase with a virtual function SayHi(). Foo1 is one of many derived classes.
class FooBase {
public:
virtual void SayHi() = 0;
};
class Foo1 : public FooBase {
public:
virtual void SayHi() {
std::cout<<"Foo1 says Hi\n";
}
};
I also have a Component class and sometimes I would like to implement Foo.. classes as Components. I've used a template class so that any subclass of FooBase can have a Component wrapper.
class FooComponentBase : public Component {
public:
virtual FooBase& GetFoo() = 0;
};
template <class T>
class FooComponent : public FooComponentBase {
private:
T m_foo;
public:
virtual FooBase& GetFoo() {return m_foo;}
};
Now FooComponentBase is an interface to components containing any subclass of FooBase:
void DoTest() {
FooComponentBase* pFooComponent = new FooComponent<Foo1>;
pFooComponent->GetFoo().SayHi(); // "Foo1 says Hi"
delete pFooComponent;
}
So far so good, this works. But it might be neater if FooComponent were inherited from FooBase, so we don't need to go through GetFoo() to access FooBase's methods.
// Inherited version
class FooComponentBase : public Component {};
template <class T>
class FooComponent : public FooComponentBase, public T {};
Unfortunately, FooComponentBase has no access to FooBase even though all of its derived classes do;
void DoTest() {
FooComponentBase* pFooComponent = new FooComponent<Foo1>;
pFooComponent->SayHi(); // Error, FooComponentBase has no SayHi() function
delete pFooComponent;
}
I can't find a way to make this work. It seems like there ought to be a way, maybe using virtual inheritance;
class FooComponentBase : public Component, virtual public FooBase {};
But that won't compile either, since we can't instantiate an abstract class. I hope my intention is clear, I'd like to make FooComponentBase an abstract base class, like FooBase but with Component inheritance, so I can use it to access every flavor of FooComponent.
Is there a neat way to do this?
If you use virtual inheritance in one place, you have to use it everywhere if you want that same base implementation to be used:
class Foo1 : public virtual FooBase {
The other way, which is not as nice but might work out for you, would be to implement all of FooBase's functions in FooComponent:
class FooComponentBase : public Component, public FooBase {
};
template <class T>
class FooComponent : public FooComponentBase {
private:
T m_foo;
public:
void SayHi() {m_foo.SayHi();}
};
Or even:
class FooComponentBase : public Component, public FooBase {
};
template <class T>
class FooComponent : public FooComponentBase, public T {
public:
void SayHi() {T::SayHi();}
};
Must virtual methods be always implemented in derived class?
Can I write something like this?
<!-- language: lang-cpp -->
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface();
};
class Derived : public BaseInterface
{
void fun_a() { ... };
};
class FinalClass : public Derived
{
void fun_b() { ... };
}
int main()
{
FinalClass test_obj;
test_obj.fun_a(); // use Derived implementation or fail ???
test_obj.fun_b(); // use own implementation
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a(); // fail or ok ???
test_interface->fun_b();
}
Is the code above correct?
Does another virtual method outflank exist?
Pure virtual methods always must be reimplemented in derived class?
Actually a derived class which is going to be instantiated.
In your code, you didn't make an object from Derived so it's OK.
Can i write something like this?
Yes.
You had some minor errors that I corrected them:
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface() {}; // You forget this
};
class Derived : public BaseInterface
{
public:
void fun_a() {} // This should be public as its base
};
class FinalClass : public Derived
{
public:
void fun_b() {} // This should be public as its base
};
int main()
{
FinalClass test_obj;
test_obj.fun_a();
test_obj.fun_b();
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a();
test_interface->fun_b();
}
It makes Derived also an abstract class which you cannot instantiate, seeing you don't implement all the virtual functions from it's base, it becomes an abstract class you cannot directly instantiate.
See here: liveworkspace.org/code/6huYU$10
For the rest, your code should work.
Code is correct.
There is no special concept for interface in C++. All are classes. Some of the class methods can be pure virtual. It only means that compiler cannot create an instance of such class.
I have trouble when designing classes like this
class C1 {
public:
void foo();
}
class C2 {
public:
void foo();
}
C1 and C2 has the same method foo(),
class Derived1 : public Base {
public:
void Update() {
member.foo();
}
private:
C1 member;
}
class Derived2 : public Base {
public:
void Update() {
member.foo();
}
private:
C2 member;
}
Update() of both Derived class are exactly the same, but the type of member is different.
So i have to copy the Update implement for every new derived class.
Is that a way to reduce this code duplication? I only come out with a solution with macro.
I think there is a more elegant way to solve this with template but I can not figure it out..
EDIT:
thanks a lot guys but i think i missed something..
1.I'm using c++
2.In reality each Derived class has about 5 members, they all afford the foo() method and are derived from the same base class. My situation is that i have already written a (very long) Update() method and it can work for every derived class without any modification. So i just copy and paste this Update() to every new class's Update() and this lead to terrible code duplication. I wonder if there is a way in which i need not to rewrite the Update() too much and can reduce the duplication.
thx again
This is exactly the sort of application that class templates are designed for. They allow functions within a class to operate on different data types, without the need to copy algorithms and logic.
This Wikipedia page will give you a good overview of templates in programming.
Here's the basic idea to get you started:
template <class T>
class CTemplateBase
{
public:
void Update()
{
member.foo();
}
private:
T member; // Generic type
}
class CDerived1 : public CTemplateBase<C1>
{
// No common algorithms required here
}
class CDerived2 : public CTemplateBase<C2>
{
// No common algorithms required here
}
If you have the control over C1 and C2, you can either define a base class or an abstract base class and handle it at Base class or third helper class.
If your Drived1 and Derived2 are same except for the type (C1 and C2) of member, then you can consider using a single class Derived and a template.
(Excuse my syntax if incorrect, i m C# dev :D )
template <class T>
class Derived : public Base {
public:
void Update() {
member.foo();
}
private:
T member;
}
Something on the above lines.
Move the method to the parent class:
class IFooable {
public:
virtual void foo() = 0;
}
class C1 : IFooable {
public:
void foo();
}
class C2 : IFooable {
public:
void foo();
}
class Base {
public:
void Update() {
member->foo();
}
private:
IFooable* member
}
class Derived1 : public Base {
Derived1 () : member(new C1()) {}
~Derived1 () { delete member; }
}
class Derived2 : public Base {
Derived2 () : member(new C2()) {}
~Derived2 () { delete member; }
}