从基 class 方法调用派生 class 的静态方法
Call static method of derived class from base class method
我想实现一个方法 CastTo(classId)
,其中 returns 其 classId 参数与参数匹配的基础对象的地址,否则 nullptr 将返回。
class A {
public:
const std::string WhoAmI () { return "A"; }
static const std::string ClassId() { return "A"; }
const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return dynamic_cast<const A*>(this);
if (classId == B.ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == C.ClassId()) return dynamic_cast<const C*>(this); //*
return nullptr;
}
//more methods
};
class B : public A{
public:
const std::string WhoAmI() { return "B"; }
static const std::string ClassId() { return "B"; }
const void* CastTo(const std::string& classId) const {
if (classId == A.ClassId()) return dynamic_cast<const A*>(this); //*
if (classId == ClassId()) return dynamic_cast<const B*>(this);
if (classId == C.ClassId()) return dynamic_cast<const C*>(this); //*
return nullptr;
}
//more methods
};
class C : public B{
public:
const std::string WhoAmI() { return "C"; }
static const std::string ClassId() { return "C"; }
const void* CastTo(const std::string& classId) const {
if (classId == A.ClassId()) return dynamic_cast<const A*>(this); //*
if (classId == B.ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == ClassId()) return dynamic_cast<const C*>(this);
return nullptr;
}
//more methods
};
不过在注释行中,我得到了错误 "typename is not allowed"。我也尝试过使用“->”而不是“。”但错误仍然存在。
我不明白为什么上面的代码不能工作,因为这些方法被声明为静态的。
这是作业的一部分,因此它必须按照我描述的方式工作,并且以下测试代码必须正常。
A* a = new C();
assert(a->Cast<C>().WhoAmI() == "C"); //Cast is a template used for
assert(a->Cast<B>().WhoAmI() == "B"); //calling CastTo
assert(a->Cast<A>().WhoAmI() == "A");
B* b = a->Cast<B>();
C* c = a->Cast<C>();
使用的模板:
template <typename T> T* Cast (void)
{ return static_cast<T*>(CastTo(T::ClassId()); }
template <typename T> const T* Cast (void) const
{ return static_cast<T*>(CastTo(T::ClassId()); }
PS:我也尝试过使用 B::ClassId() 但随后出现错误“'B' 不是 class 或命名空间名称”,但是只有当我调用 derived from base 时。
PS1:我不知道代码是否会按我希望的那样工作,因为我还没有能够消除错误。
A::CastTo
中的语法错误:
if (classId == B.ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == C.ClassId()) return dynamic_cast<const C*>(this);
你需要使用
if (classId == B::ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == C::ClassId()) return dynamic_cast<const C*>(this);
需要在 B::CastTo
和 C::CastTo
中进行类似的更改。
但是,要使其正常工作,您必须在 class 之外实现该功能,最好是在您可以使用 #include "B.h"
和 #include "C.h"
的 .cpp 文件中。
更好的方法
class A {
public:
static const std::string ClassId() { return "A"; }
// Class A should know nothing about its derived classes.
virtual const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return (this);
return nullptr;
}
};
class B : public A{
public:
static const std::string ClassId() { return "B"; }
// Class B knows about itself and its base class, noting else.
virtual const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return (this);
return A::ClassId(classId);
}
};
class C : public B{
public:
static const std::string ClassId() { return "C"; }
// Class C knows about itself and its base class, noting else.
virtual const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return (this);
return A::ClassId(classId);
}
};
我想实现一个方法 CastTo(classId)
,其中 returns 其 classId 参数与参数匹配的基础对象的地址,否则 nullptr 将返回。
class A {
public:
const std::string WhoAmI () { return "A"; }
static const std::string ClassId() { return "A"; }
const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return dynamic_cast<const A*>(this);
if (classId == B.ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == C.ClassId()) return dynamic_cast<const C*>(this); //*
return nullptr;
}
//more methods
};
class B : public A{
public:
const std::string WhoAmI() { return "B"; }
static const std::string ClassId() { return "B"; }
const void* CastTo(const std::string& classId) const {
if (classId == A.ClassId()) return dynamic_cast<const A*>(this); //*
if (classId == ClassId()) return dynamic_cast<const B*>(this);
if (classId == C.ClassId()) return dynamic_cast<const C*>(this); //*
return nullptr;
}
//more methods
};
class C : public B{
public:
const std::string WhoAmI() { return "C"; }
static const std::string ClassId() { return "C"; }
const void* CastTo(const std::string& classId) const {
if (classId == A.ClassId()) return dynamic_cast<const A*>(this); //*
if (classId == B.ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == ClassId()) return dynamic_cast<const C*>(this);
return nullptr;
}
//more methods
};
不过在注释行中,我得到了错误 "typename is not allowed"。我也尝试过使用“->”而不是“。”但错误仍然存在。 我不明白为什么上面的代码不能工作,因为这些方法被声明为静态的。
这是作业的一部分,因此它必须按照我描述的方式工作,并且以下测试代码必须正常。
A* a = new C();
assert(a->Cast<C>().WhoAmI() == "C"); //Cast is a template used for
assert(a->Cast<B>().WhoAmI() == "B"); //calling CastTo
assert(a->Cast<A>().WhoAmI() == "A");
B* b = a->Cast<B>();
C* c = a->Cast<C>();
使用的模板:
template <typename T> T* Cast (void)
{ return static_cast<T*>(CastTo(T::ClassId()); }
template <typename T> const T* Cast (void) const
{ return static_cast<T*>(CastTo(T::ClassId()); }
PS:我也尝试过使用 B::ClassId() 但随后出现错误“'B' 不是 class 或命名空间名称”,但是只有当我调用 derived from base 时。
PS1:我不知道代码是否会按我希望的那样工作,因为我还没有能够消除错误。
A::CastTo
中的语法错误:
if (classId == B.ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == C.ClassId()) return dynamic_cast<const C*>(this);
你需要使用
if (classId == B::ClassId()) return dynamic_cast<const B*>(this); //*
if (classId == C::ClassId()) return dynamic_cast<const C*>(this);
需要在 B::CastTo
和 C::CastTo
中进行类似的更改。
但是,要使其正常工作,您必须在 class 之外实现该功能,最好是在您可以使用 #include "B.h"
和 #include "C.h"
的 .cpp 文件中。
更好的方法
class A {
public:
static const std::string ClassId() { return "A"; }
// Class A should know nothing about its derived classes.
virtual const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return (this);
return nullptr;
}
};
class B : public A{
public:
static const std::string ClassId() { return "B"; }
// Class B knows about itself and its base class, noting else.
virtual const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return (this);
return A::ClassId(classId);
}
};
class C : public B{
public:
static const std::string ClassId() { return "C"; }
// Class C knows about itself and its base class, noting else.
virtual const void* CastTo(const std::string& classId) const {
if (classId == ClassId()) return (this);
return A::ClassId(classId);
}
};