【问题标题】:Referencing my own object: When is it allowed and when is it not?引用我自己的对象:什么时候允许,什么时候不允许?
【发布时间】:2021-08-06 22:16:10
【问题描述】:

看起来我有时可以引用自己的对象,有时却不能——例如:

#ifndef TILE_H
#define TILE_H

#include "position.h"
#include <vector>
#include <tuple>

using std::vector;
using std::pair;
namespace Game {
class tile
{
public:
    tile(int x, int y, int value);
    void savePosition();
    void updatePosition(int x, int y);
    void updatePosition(gridSquare g);
    vector<pair<gridSquare, int>> serialize();
    bool isEqualTo(tile rhs /* why is this allowed? */ ){ 
       return position.x == rhs.position.x && position.y == rhs.position.y && value == rhs.value;
    }
public:

    gridSquare position;
    int value;

    gridSquare previousPosition;
    tile mergedFrom; // but this not?

};
}
#endif // TILE_H

不应该两者都不允许吗?第二个抛出“不完整类型”错误,但第一个不会抛出任何类型的错误,而它仍然引用可能不完整的类。怎么了?为什么第一个允许,而第二个不允许?是不是因为在类完成定义之前没有使用第一个?

【问题讨论】:

  • 忽略c++角度;允许递归结构定义是不正常的;例如struct a { int b,c; struct a d; };,这是您正在尝试做的事情的整理版本。也就是说,总是值得尝试您的编译器支持的每一个可以想象的标准版本,看看是否可行。
  • 对于函数调用,编译器不需要知道完整的定义;当它计数时,当函数被调用时,它将拥有它。对于变量声明,如果没有其他原因,它需要完整的定义,只是为了知道要保留多少空间。
  • 如果每个tile 包含一个tile,那么每个tile 包含无限数量的tiles。这是没有意义的。在 C++ 中,对象是对象。 tile 不能不是 tile,所以没有办法打破递归

标签: c++ object


【解决方案1】:

函数声明不需要其参数类型是完整的。

struct A; 
void f(A); // fine

该要求仅适用于函数定义

struct A;
void f(A); // fine
// void f(A) { } // not fine
struct A { };
void f(A) { } // fine

类成员函数有一个特殊的例外:类中任何函数的定义实际上都隐式地从其声明中分离出来并移出类

struct A { void f(A) { } /* A is indeed incomplete within its definition */ };
// but f can be defined "within" it anyway because this is made equivalent to
struct A { inline void f(A); };
inline void A::f(A) { } // fine

从技术上讲,类成员函数的主体(但不是声明)被视为complete-class context。粗略地说,类主体中的声明不在完整类上下文中,因此他们认为类类型是不完整的。但是,与这些声明关联的定义/初始化器位于完整类上下文中,因此它们将类类型视为完整。

【讨论】:

    猜你喜欢
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多