C 错误:从(基类模板)到子类的无效转换
C++ error: invalid conversion from (base class template) to subclass
我一直在项目中使用主题观察者模式。由于主题观察者和消息类型的数量已增长到5 ,因此我发现自己为每个复制了相同的代码模式。我正在尝试切换到主题观察者模式的类模板。但是我陷入了我无法解决的编译器错误(尽管做出了努力(:
:Building file: ../main.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
../main.cpp: In instantiation of ‘Observer<T_subject, T_message>::~Observer() [with T_subject = RotationSubject; T_message = long unsigned int]’:
../main.cpp:49:7: required from here
../main.cpp:39:15: error: invalid conversion from ‘Observer<RotationSubject, long unsigned int>* const’ to ‘RotationObserver*’ [-fpermissive]
~Observer(){ subject->UnregisterObserver( this ); }
^
../main.cpp:10:7: error: initializing argument 1 of ‘void Subject<T_observer, T_message>::UnregisterObserver(T_observer*) [with T_observer = RotationObserver; T_message = long unsigned int]’ [-fpermissive]
void UnregisterObserver( T_observer* observer ){
^
make: *** [main.o] Error 1
最小工作示例代码是:
#include <vector>
template <class T_observer, typename T_message> class Subject
{
public:
void RegisterObserver( T_observer* observer ){
observers.push_back(observer);
}
void UnregisterObserver( T_observer* observer ){
for (auto itr = begin(observers); itr != end(observers); itr++){
if (*itr == observer){
itr = observers.erase(itr);
if (itr == observers.end()) break;
}
}
}
void NotifyObservers( T_message message ){
for(auto const& itr : observers){
itr->ReceiveMessage( message );
}
}
std::vector < T_observer * > observers;
};
template <class T_subject, typename T_message> class Observer
{
public:
Observer( T_subject* subject )
: subject( subject )
{
subject->RegisterObserver( this );
}
~Observer(){ subject->UnregisterObserver( this ); }
virtual void ReceiveMessage( T_message message ) {};
// Observer sub-classes define ReceiveMessage
T_subject* subject;
};
class RotationSubject;// forward declaration prevents circular dependency
class RotationObserver : public Observer< RotationSubject, unsigned long>
{
public:
RotationObserver( RotationSubject* rotation_subject );
};
class RotationSubject : public Subject< RotationObserver, unsigned long>
{ };
int main(int argc, char * argv[]){
RotationSubject* pRotSubject = new RotationSubject( );
RotationObserver* pRotObserver = new RotationObserver( pRotSubject );
pRotObserver->~RotationObserver();
return 0;
}
目的是定义从这些基类模板中得出的子类,如RotationSubject
和RotationObserver
所示。类型标识符T_observer
和T_subject
的动机是要具体的,例如可以配对哪些子类,例如RotationObservers
只能观察RotationSubjects
,并接收旋转消息类型(在此示例中T_message
是unsigned long
(。
如果我正确读取了错误消息,则Observer<RotationSubject, long unsigned int>* const
是不是 a RotationObserver*
,或者编译器不知道如何转换。
我探索了循环依赖性和const作为原因,没有成功。
请帮助我了解此错误消息的原因,并在可能的情况下进行最小的编辑以更正。这是我的主要问题。
我对完全不同的设计开放,并提出了改进的建议。
您正在丢弃const
预选赛。没有const_cast
和一个充分的理由,您将无法做到这一点。
您还试图转换为"错误"方向。并非每个Observer< RotationSubject, unsigned long>
都必须是RotationObserver
,尽管相反是正确的。您可以通过dynamic_cast
(或static_cast
和Promise(使其使用。
进一步搜索出现了一些有用的链接,这些链接与模板 - 观察者模式:(https://www.codeproject.com/articles/3267/implementing-a-subject-observer-pattern-with-templ((基于模板的主题观察者模式 - 我应该使用static_cast或dynamic_cast((我应该使用模板的主题观察者模式中的动态铸造(
以下代码是有效的更正版本。它源自第一个链接。根据@boundaryIblosition的答案,它在模板主题中使用static_cast
:: notifyObservers((方法在获取指向主题子类的指针。我对这个概念不满意100%,但它有效。根据我的理解,魔术酱是Subject
中奇怪的重复模板图案的使用。特别是class Temperature : public Subject<Temperature>
(为了清楚起见,删除了第二个模板标识符(。而在我使用class RotationSubject : public Subject<RotationObserver>
之前,这是完全不同的继承。Observer
子类PanicSiren
也具有不同的继承。
请注意,我的模板将RegisterObserver
和UnregisterObserver
移至Observer
CTOR和DTOR。不需要,只是我喜欢的方式。我还添加了消息类型模板标识符T_message
,该标识符允许各种消息类型。
我很高兴,因为预期的设计是没有大量重写的:(。
#include <vector>
#include <iostream>
template <typename T_subject, typename T_message> class Observer{
public:
Observer( T_subject* subject ) : subject(subject) { subject->RegisterObserver( *this ); }
virtual ~Observer() { subject->UnregisterObserver( *this ); }
virtual void ReceiveMessage( T_subject* subject, T_message message ) = 0;// =0 requires subclasses to define
T_subject* subject;
};
template <class T_subject, class T_message> class Subject{
public:
virtual ~Subject() {}
void NotifyObservers( T_message message ){
typename std::vector<Observer<T_subject,T_message> *>::iterator it;
for ( it=m_observers.begin(); it!=m_observers.end(); ++it){
T_subject* this_subject_subclass = static_cast<T_subject*>(this);// pointer to _subclass_ type, curiously not yet defined ;)
(*it)->ReceiveMessage( this_subject_subclass, message );
}
}
void RegisterObserver( Observer<T_subject,T_message> &observer ){
m_observers.push_back( &observer ); }
void UnregisterObserver( Observer<T_subject,T_message> &observer ){
for (auto itr = begin(m_observers); itr != end(m_observers); itr++){
if (*itr == &observer){
itr = m_observers.erase(itr);
if (itr == m_observers.end()) break;
}
}
}
private:
std::vector<Observer<T_subject,T_message> *> m_observers;
};
class Temperature : public Subject<Temperature,unsigned long> {};
class PanicSiren : public Observer<Temperature,unsigned long>
{
public:
PanicSiren(Temperature* subject)
: Observer<Temperature,unsigned long>::Observer(subject) {}
void ReceiveMessage( Temperature *subject, unsigned long message ){
std::cout << "Temperature changed to " << message <<", sounding the siren"
<< std::endl;
}
};
int main(int argc, char * argv[]){
Temperature* temp = new Temperature();
PanicSiren* panic = new PanicSiren( temp );
temp->NotifyObservers( 42 );
return 0;
}
- 将父类对象强制转换为子类的问题
- 将QOpenGLWidget子类转换为使用Metal而不是OpenGL的子类是否可行?
- 无法将模板子类强制转换为其他模板实例化
- 从父类的向量访问子类函数,而无需向下转换
- 带有基类指针的强制转换向量,指向子类
- 将子类的成员函数强制转换为父类
- C++ QList 中项目的 QT 强制转换到子类
- 将"this"从父类方法转换为子类方法是一种好的做法吗?
- 将子类转换为基类
- 无法将参数 3 从 'const QGraphicsItem *' 转换为 'const QObject *',这是指针,对象是 QGraphicsObject 的子类
- C 错误:从(基类模板)到子类的无效转换
- 从子类到具有相同基数的抽象子类的隐式转换
- 子类ConstexPR类以获得不同的用户定义的转换行为
- 如何在模板子类中重写转换运算符C++
- 模板化函数指针从子类到父类的转换
- 无法将超类强制转换为子类
- 将子类列表转换为超类列表
- C++从接口类到子类的转换无效
- 将空基类指针强制转换为子类指针
- 如何在 c++ 中将类强制转换为其子类