带有模板的 C++ 运行时多态性
C++ runtime polymorphism with templates
我的程序有可观察对象和观察者。这是可观察的。
template <typename E>
class Observable {
private:
std::list<E> observers;
public:
void addObserver(E observer) {
observers.push_back(observer);
}
void notifyAll() {
for (auto & observer: observers) {
observer.doSomething();
}
}
};
有一个基础 AnimalObserver
和派生观察者 CatObserver
和 DogObserver
。 AnimalObserver
有一个虚方法 void doSomething()
。 CatObserver
和 DogObserver
实现此方法。
class DogObserver : public AnimalObserver {
public:
DogObserver() = default;
void doSomething() const {
std::cout << "woof!";
}
};
class CatObserver : public AnimalObserver {
public:
CatObserver() = default;
void doSomething() const {
std::cout << "meow!";
}
};
我这样创建我的 Observable 和 运行 我的程序:
auto observable = Observable<AnimalObserver>();
auto cat = CatObserver();
auto dog = DogObserver();
observable.register(cat);
observable.register(dog);
observable.notifyAll();
发生的情况是 AnimalObserver
的 doSomething 方法被调用了两次,而不是 CatObserver
和 DogObserver
doSomething 方法被调用。我想调用派生 类 的 doSomething 方法,而不是父 类.
我想做的是保留一个从 AnimalObserver
派生的不同观察者的列表,并调用它们的 doSomething
行为而不是虚函数。
如果之前有人问过这个问题,我深表歉意,但我什至不确定要搜索什么。我正在阅读有关模板的内容,但迷路了。
唯一的问题是:您必须在 Observable class 中存储一个指向基 class AnimalObserver 的指针。您可以通过多种方式执行此操作。 unique_ptr<> 想到了。
这是一个带有一些提示的实现。神箭:https://godbolt.org/z/1Gq35G
#include <list>
#include <iostream>
#include <memory>
using namespace std;
struct AnimalObserver
{
virtual ~AnimalObserver() { }
// Hint 1: Declare abstract so that it won't even compile if you use the
// base class directly in a collection - i.e. and not a pointer to the base.
virtual void doSomething() const = 0;
};
template <typename E>
class Observable {
private:
typedef unique_ptr< E > _TyPtrContained;
std::list<_TyPtrContained> observers;
public:
void addObserver( unique_ptr< E > && rrobserver ) {
// Remember that inside a method that receives a rvalue-reference,
// it is an lvalue-reference and must be std::move()'d when passing to a
// method that accepts an rvalue-reference.
observers.push_back( std::move( rrobserver ) );
}
void notifyAll() {
for (auto & observer: observers) {
observer->doSomething();
}
}
};
class DogObserver : public AnimalObserver {
public:
DogObserver() = default;
// Hint 2: Use override to ensure that you are overriding an actual
// virtual and not just declaring a method with a different signature
// than the base.
void doSomething() const override {
std::cout << "woof!";
}
};
class CatObserver : public AnimalObserver {
public:
CatObserver() = default;
void doSomething() const override {
std::cout << "meow!";
}
};
int
main()
{
auto observable = Observable<AnimalObserver>();
// Hint 3: You can assign a unique_ptr<derived> to a unique_ptr<base>.
unique_ptr< AnimalObserver > cat = make_unique< CatObserver >();
unique_ptr< AnimalObserver > dog = make_unique< DogObserver >();
// We move the local unique_ptrs into the addObserver method so that
// they are then moved into the list using the rvalue-reference version
// of list<>::push_back().
observable.addObserver( std::move( cat ) );
observable.addObserver( std::move( dog ) );
observable.notifyAll();
// And, voila, things work...
}
我的程序有可观察对象和观察者。这是可观察的。
template <typename E>
class Observable {
private:
std::list<E> observers;
public:
void addObserver(E observer) {
observers.push_back(observer);
}
void notifyAll() {
for (auto & observer: observers) {
observer.doSomething();
}
}
};
有一个基础 AnimalObserver
和派生观察者 CatObserver
和 DogObserver
。 AnimalObserver
有一个虚方法 void doSomething()
。 CatObserver
和 DogObserver
实现此方法。
class DogObserver : public AnimalObserver {
public:
DogObserver() = default;
void doSomething() const {
std::cout << "woof!";
}
};
class CatObserver : public AnimalObserver {
public:
CatObserver() = default;
void doSomething() const {
std::cout << "meow!";
}
};
我这样创建我的 Observable 和 运行 我的程序:
auto observable = Observable<AnimalObserver>();
auto cat = CatObserver();
auto dog = DogObserver();
observable.register(cat);
observable.register(dog);
observable.notifyAll();
发生的情况是 AnimalObserver
的 doSomething 方法被调用了两次,而不是 CatObserver
和 DogObserver
doSomething 方法被调用。我想调用派生 类 的 doSomething 方法,而不是父 类.
我想做的是保留一个从 AnimalObserver
派生的不同观察者的列表,并调用它们的 doSomething
行为而不是虚函数。
如果之前有人问过这个问题,我深表歉意,但我什至不确定要搜索什么。我正在阅读有关模板的内容,但迷路了。
唯一的问题是:您必须在 Observable class 中存储一个指向基 class AnimalObserver 的指针。您可以通过多种方式执行此操作。 unique_ptr<> 想到了。
这是一个带有一些提示的实现。神箭:https://godbolt.org/z/1Gq35G
#include <list>
#include <iostream>
#include <memory>
using namespace std;
struct AnimalObserver
{
virtual ~AnimalObserver() { }
// Hint 1: Declare abstract so that it won't even compile if you use the
// base class directly in a collection - i.e. and not a pointer to the base.
virtual void doSomething() const = 0;
};
template <typename E>
class Observable {
private:
typedef unique_ptr< E > _TyPtrContained;
std::list<_TyPtrContained> observers;
public:
void addObserver( unique_ptr< E > && rrobserver ) {
// Remember that inside a method that receives a rvalue-reference,
// it is an lvalue-reference and must be std::move()'d when passing to a
// method that accepts an rvalue-reference.
observers.push_back( std::move( rrobserver ) );
}
void notifyAll() {
for (auto & observer: observers) {
observer->doSomething();
}
}
};
class DogObserver : public AnimalObserver {
public:
DogObserver() = default;
// Hint 2: Use override to ensure that you are overriding an actual
// virtual and not just declaring a method with a different signature
// than the base.
void doSomething() const override {
std::cout << "woof!";
}
};
class CatObserver : public AnimalObserver {
public:
CatObserver() = default;
void doSomething() const override {
std::cout << "meow!";
}
};
int
main()
{
auto observable = Observable<AnimalObserver>();
// Hint 3: You can assign a unique_ptr<derived> to a unique_ptr<base>.
unique_ptr< AnimalObserver > cat = make_unique< CatObserver >();
unique_ptr< AnimalObserver > dog = make_unique< DogObserver >();
// We move the local unique_ptrs into the addObserver method so that
// they are then moved into the list using the rvalue-reference version
// of list<>::push_back().
observable.addObserver( std::move( cat ) );
observable.addObserver( std::move( dog ) );
observable.notifyAll();
// And, voila, things work...
}