【问题标题】:Call static method of derived class from base class method从基类方法调用派生类的静态方法
【发布时间】:2015-04-08 15:54:12
【问题描述】:

我想实现一个方法CastTo(classId),它返回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
};

但是,在注释行中,我收到错误“不允许使用类型名”。我也尝试使用“->”而不是“。”但错误仍然存​​在。 我不明白为什么上面的代码不起作用,因为方法被声明为静态的。

这是作业的一部分,所以它必须按照我描述的方式工作,并且下面的测试代码必须没问题。

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'不是类或命名空间名称”,但只有当我调用派生自基时。

PS1:我不知道代码是否能按我的意愿工作,因为我还没有能够摆脱错误。

【问题讨论】:

  • 这是一个非常糟糕的主意,因为调用者无法正确使用结果
  • 您返回的是void *,所以这无论如何都不能作为演员表。为什么不直接使用已经返回nullptrdynamic_cast?实际上,在看到您的编辑后,我真的不知道您要做什么。
  • 使用模板方法模式
  • @Ezra 你能解释一下你的意思吗?
  • 我担心这个设计是做什么用的?如果这个层次结构增长,有多少代码被破坏并且必须更新?

标签: c++ inheritance casting static-methods dynamic-cast


【解决方案1】:

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::CastToC::CastTo 需要进行类似的更改。

但是,要使其工作,您必须在类外实现该功能,最好是在一个 .cpp 文件中,您可以在其中使用 #include "B.h"#include "C.h"

更好的方法

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);
    }
};

【讨论】:

  • 但是将所有派生类头文件包含到基类中是一种好习惯吗?如果继续继承更多的类怎么办?
  • 我真正想要的是能够将任何类转换为任何类。查看添加的测试代码。
  • @NenaB,当您分发代码的点点滴滴时,它并不是很有帮助。您正在使用不在您发布的代码中的Cast&lt;A&gt;()WhoAmI()。请看How do I ask a good question?
  • 认为这些行不是必需的,因为它们是在分配时给出的,并且不能为实现而更改。代码已添加。
  • 第一种方法奏效了。虽然这仍然不是一个好方法,但我会接受这个答案,直到找到更好的答案。
猜你喜欢
  • 2012-05-24
  • 2010-10-10
  • 2012-06-25
  • 2011-03-05
  • 2013-04-24
  • 1970-01-01
  • 2014-03-17
  • 2013-03-23
相关资源
最近更新 更多