[英]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
行為而不是虛擬 function。
如果以前有人問過這個問題,我深表歉意,但我什至不確定要搜索什么。 我正在閱讀有關模板的信息,但迷路了。
唯一的問題是:您必須在 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...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.