【问题标题】:I'm messing up my inheritance我搞砸了我的遗产
【发布时间】:2011-06-14 17:35:46
【问题描述】:

所以我有一个 Piece 类应该代表棋盘上的棋子,我计划从中继承另外两个类。但是,我在这样做时遇到了很多问题。这是到目前为止的相关代码。

///
/// PIECE CLASS HERE
/// this is an abstract class from which Barrier and Pawn inherit.

class Piece
{
public:
    Piece(Space* start);
    sf::Shape m_Circle;
protected:
    int m_X;
    int m_Y;
    int m_radius;
    Space* CurrentSpace;
};

Piece::Piece(Space* start):
    m_X(start->GetX()),
    m_Y(start->GetY()),
    m_radius(14),
    CurrentSpace(start)
{}

///
/// BARRIER CLASS HERE
/// these are the white stones that block a player's path

class Barrier : public Piece
{
public:
    Barrier(Space* initial);
    void Move(Space* target, bool isCapturing);
};

Barrier::Barrier(Space* initial)
{
    Piece(initial);
    m_Circle = sf::Shape::Circle((float)m_X, (float)m_Y, (float)m_radius, sf::Color(255, 255, 255));
    Move(initial);
}

void Barrier::Move(Space* target, bool isCapturing)
{
    int xChange = abs(target->GetX() - m_X);
    int yChange = abs(target->GetY() - m_Y);
    m_Circle.Move((float)xChange, (float)yChange);
    CurrentSpace.ToggleOccupied();
    if(!isCapturing)
    {
        (*target).ToggleOccupied();
    }
    CurrentSpace = target;
}

我遇到了很多我不明白的错误,尤其是:

no matching function for call to Piece::Piece()
declaration of 'Piece initial' shadows a parameter
no matching function for call to 'Barrier::Move(Piece&)'
request for member 'ToggleOccupied' in '((Barrier*)this)->Barrier::<anonymous>.Piece::CurrentSpace', which is of non-class type 'Space*'|

作为 C++ 新手,我不明白其中有什么问题。我试图构建我的代码,类似于我在学习 C++ 的书中找到的代码,但显然我忽略了一些微妙之处。我尝试调用的所有函数似乎都存在于适当的位置,我认为我用与原型中相同的值来定义它们。

【问题讨论】:

    标签: c++ inheritance constructor sfml


    【解决方案1】:

    第一个错误是由这个引起的:

    Barrier::Barrier(Space* initial)
    {
        Piece(initial);
        m_Circle = sf::Shape::Circle((float)m_X, (float)m_Y, (float)m_radius, sf::Color(255, 255, 255));
        Move(initial);
    }
    

    需要看起来像:

    Barrier::Barrier(Space* initial) : Piece(initial)
    {
        m_Circle = sf::Shape::Circle((float)m_X, (float)m_Y, (float)m_radius, sf::Color(255, 255, 255));
        Move(initial);
    }
    

    基类的构造函数在你的构造函数之前运行(无论如何)——如果它需要初始化列表中的参数,你需要将参数传递给它。

    我不确定其他错误,因为我不知道它们发生在哪一行。

    【讨论】:

    • 第二个错误是相同的结果:类大括号内的Piece(initial) 声明了一个局部变量,然后Move(initial) 试图将Piece 左值传递给Barrier::Move 函数。
    【解决方案2】:

    行中的括号

    Piece(initial);
    

    被编译器忽略。您正在声明一个与参数同名的变量:

    Piece initial;
    

    要使用initial 初始化Piece 基础对象,您必须使用成员初始化器列表:

    Barrier::Barrier(Space* initial) : Piece(initial)
    

    另外,Move 函数需要两个参数,但您只传递了一个。你忘记了布尔值。

    【讨论】:

    • 不,我认为他只是在调用函数并传递参数initial
    • @Billy: Piece 不是函数,但Move 是。
    • Piece(initial); 正在声明一个变量,Move(initial); 正在调用一个函数。
    • @Xeo:你可以用括号消除歧义:(std::string(argv)); 将创建并立即销毁一个字符串对象。或者更确切地说,如果有合适的构造函数,它会。
    • @Billy:对不起,我很迂腐。我没办法,我是 C++ 程序员 ;)
    【解决方案3】:

    很好的答案,所有。加上最后令人生畏的一行

    request for member 'ToggleOccupied' in '((Barrier*)this)-&gt;Barrier::&lt;anonymous&gt;.Piece::CurrentSpace', which is of non-class type 'Space*'|

    是由

    引起的

    CurrentSpace.ToggleOccupied();

    你已经将 CurrentSpace 声明为一个指针,所以它应该是

    CurrentSpace->ToggleOccupied();

    【讨论】:

    • 哇,你们太棒了。希望我的编码技能最终能够达到我可以帮助他人的水平!我修复了它,一切都恢复了。谢谢一百万!
    【解决方案4】:

    如果你想初始化超类,你应该这样做:

    Barrier(Space* initial): 
        Piece(initial) {
        ...
    }
    

    如果您没有显式初始化基类型,编译器将尝试通过调用带有空参数列表的构造函数来初始化它,如下所示:

    Barrier(Space* initial):
        Piece() {
        ... 
    }
    

    但是由于您没有为 Piece 定义一个接受零参数的构造函数,因此您会得到您所描述的编译器错误。

    【讨论】: