我有以下课程:
class Box{...};
class MyBox : public Box{...};
模板:
template <type T>
class ObjectManager{...};
我在其他课程中使用的是:
class Engine{
ObjectManager<Box> * manager = nullptr;
...
};
然后我扩展(实现)Engine
接口:
class MyEngine : public Engine{...}
在该实施中(不早!)我知道manager
应该是这样的:
MyEngine::MyEngine(){
manager = new ObjectManager<MyBox>();
}
但是由于类型冲突(ObjectManager<Box>
和ObjectManager<MyBox>
之间的转换),即使MyBox
继承自Box
,这也会给我一个错误。
有没有解决这个问题的方法? 我不想修改 Box
,MyBox
,{{1 }和ObjectManager
类。
答案 0 :(得分:1)
Templatize Engine然后继承MyEngine with Engine,携带你想要的Box模板实例。像这样:(http://codepad.org/SZMSbCRB)
#include <iostream>
using namespace std;
class Box{
};
class MyBox : public Box{
};
template <typename T>
class ObjectManager{
};
template <typename T>
class Engine{
public:
ObjectManager<T*> * manager;
};
class MyEngine : public Engine<MyBox>{
public:
MyEngine(){
manager = new ObjectManager<MyBox*>();
cout<<"myEngine created"<<endl;
}
};
int main() {
MyEngine eng = MyEngine();
return 0;
}
这里的好处是,如果明天你创建一个新的Box,即MyBox2,并且想要为此创建一个自定义引擎MyEngine2,只需继承MyEngine : public Engine <MyBox2>
。只需确保处理类型转换。
据我记忆,在Java中,您可以将Engine声明为类似Engine<extends T>
的内容,它允许您使用提供的模板T的任何子类型实例化Engine。这是一种更安全,更好的方法,但我不知道C ++是否提供了类似的东西。
希望它有所帮助。
答案 1 :(得分:0)
如果不以某种方式改变设计,这是不可能的。
ObjectManager<Box>
只是不是ObjectManager<MyBox>
而且它不是它的基类,但只有模板参数是基础的并且相互派生。
如果ObjectManager
使用指针或智能指针作为“托管”对象......
template <class T>
class ObjectManager
{
T * object;
public:
ObjectManager(T * ptr) : object(ptr) { }
};
...您可以使用指向派生对象的指针构造ObjectManager
:
class MyEngine : public Engine
{
MyEngine()
{
manager = new ObjectManager<Box>(new MyBox);
}
};
如果Engine
是抽象界面,您还可以在MyEngine
中拥有自己的经理并使用它来实施MyEngine
class MyEngine : public Engine
{
ObjectManager<MyBox> * mymanager;
MyEngine() : Engine(), mymanager(new ObjectManager<MyBox>)
{ }
};
答案 2 :(得分:0)
考虑为ObjectManager
使用包装
如果NOTE
和T
不兼容,BaseT
会标记无法编译的行。
假设:
template<class T>
ObjectManager{
T* objectAtIndex(size_t i); // As an example.
void insertAtIndex(T* object, size_t i); // As an example.
};
打包机:
template<class T, class BaseT>
class MyObjectManager
{
public:
ObjectManager<BaseT>* manager; // public for simplicity only!
T* objectAtIndex(size_t i){
return static_cast<T*>(manager->objectAtIndex(i)); // <- NOTE
}
void insertAtIndex(T* object, size_t i){
manager->insertAtIndex(object, i); // <- NOTE
}
};
用法:
class MyEngine : public Engine
{
MyObjectManager<MyBox, Box> my_manager;
MyEngine(){
// Setup the manager(s).
manager = new ObjectManager<Box>();
my_manager.manager = manager;
// Example usage.
my_manager.insertAtIndex(new MyBox(), 0);
MyBox* p = my_manager.objectAtIndex(0);
}
};
答案 3 :(得分:0)
您可以提供支持转换的实现。这应该类似于std::unique_ptr
可以从派生指针类型隐式转换为基指针类型的方式。
#include <iostream>
#include <memory>
#include <vector>
class Box
{
public:
virtual ~Box() {}
virtual void foo() = 0;
};
class MyBox : public Box
{
public:
virtual ~MyBox() {}
virtual void foo() override
{
std::cout << "MyBox::foo()\n";
}
};
template<typename T>
class ObjectManager
{
public:
ObjectManager() {}
void add(T *object)
{
objects.emplace_back(object);
}
template<typename U>
ObjectManager<T> &operator=(ObjectManager<U> &other)
{
return *this;
}
std::size_t size() const
{
return objects.size();
}
T& operator[](std::size_t i)
{
return *objects[i];
}
private:
std::vector<std::unique_ptr<T>> objects;
};
class Engine
{
public:
ObjectManager<Box> manager;
};
class MyEngine : public Engine
{
public:
MyEngine()
{
manager = ObjectManager<MyBox>();
manager.add(new MyBox());
}
};
int main()
{
MyEngine engine;
for (std::size_t i = 0; i < engine.manager.size(); ++i)
{
engine.manager[i].foo();
}
return 0;
}
MyBox::foo()
这可能有助于说明如何实施转化。
template<typename T>
class MyPointer
{
public:
MyPointer() :
mPointer(nullptr)
{
// Do nothing
}
template<typename U>
MyPointer(MyPointer<U> &other) :
mPointer(other.mPointer)
{
other.mPointer = nullptr;
}
MyPointer(T *pointer) :
mPointer(pointer)
{
// Do nothing
}
template<typename U>
MyPointer<T> &operator=(MyPointer<U> &other)
{
mPointer = other.mPointer;
other.mPointer = nullptr;
return *this;
}
~MyPointer()
{
delete mPointer;
}
T* operator->()
{
return mPointer;
}
private:
template<typename U> friend class MyPointer;
T* mPointer;
};
int main()
{
{
MyPointer<MyBox> myBox(new MyBox());
MyPointer<Box> box;
box = myBox;
box->foo();
}
{
MyPointer<MyBox> myBox(new MyBox());
MyPointer<Box> box(myBox);
box->foo();
}
return 0;
}
MyBox::foo()
MyBox::foo()