c++中声明对象和使用类型定义的顺序

The order in which to declare objects and using typedef in C++

本文关键字:类型 定义 顺序 声明 对象 c++      更新时间:2023-10-16

考虑一个类a、STL容器B和该容器的二进制谓词C。

容器B用于类A,但类A也用于二元谓词c。

struct C{
  bool operator()(A const &a, A const &b){
    return a.compare_variable < b.compare_variable;
  }
};

我们需要这个谓词来定义容器,容器使用它来对其元素排序。

因为容器声明变得相当长,所以我使用了typedef来简化声明。

typedef B<A, vector<A>, C> type;

最后,我的目标是在类a中声明容器B(其声明缩写为"type"),即作为静态公共成员变量。

class A{
  public:
  type container1, container2;
};

声明A、B和C的正确顺序是什么?

我尝试了以下顺序的变化:

  • 首先声明类A,然后是结构体C,最后是类型定义,我得到的错误是container1, container2没有命名类型——类型在类声明时不存在;

  • 首先是typepedef: loads of errors——类和结构都还没有定义;

  • 首先声明类,并在public:节中定义该结构体的类型;错误指出第三个模板参数(C)无效——它尚未定义;
  • 首先声明结构:错误表示类尚未定义。

我使用的方法是否不必要地麻烦,是否存在更优雅的解决方案?

重要警告: std::vector等标准库容器在技术上不支持不完整类型。用不完整类型实例化它们是未定义的行为。在A的定义中,A类型是不完整的,这意味着你不能可靠地使用,例如,在A的定义中,std::vector<A>类型的成员。因此,您可能希望使用Boost的容器之类的东西来保证对不完整类型的支持。

下面的讨论假设Bvector支持不完全类型的实例化。如果他们不这样做,你就不可能做你想做的事。


首先,找出依赖关系:

struct C {
  bool operator()(A const &a, A const &b){
    return a.compare_variable < b.compare_variable;
  }
};

定义C本身,包括声明 C::operator(),只需要前向声明A。但是,定义 C::operator()需要完整地定义A,因为函数体引用了A的一个成员。

typedef B<A, vector<A>, C> type;

定义type只需要前向声明AvectorBC。typedef本身不会触发模板的实例化。

class A{
public:
    type container1, container2;
};

这会触发B<A, vector<A>, C>的实例化,需要B的完整定义。容器也可能要求比较器C是一个完整类型,因为它们需要存储它的副本。

所以,简而言之:

  • 定义C需要前向声明A。定义C::operator()需要完整定义A
  • 定义type需要前向声明ABC
  • 定义A需要完整定义BC

一旦你整理了依赖项,你就可以编写代码了。假设B是通过包含适当的头定义的:

class A;     // Forward declare A for C's definition
struct C {
  bool operator()(A const &a, A const &b);
};
typedef B<A, vector<A>, C> type;
class A{
public:
    type container1, container2;
};
inline bool C::operator()(A const &a, A const &b){
  return a.compare_variable < b.compare_variable;
}

注意,你需要在a中创建一个compare_variable成员。

你想要这样的东西吗?

class A {
  struct C{
    bool operator()(A const &, A const &);
  };
  typedef B<A, vector<A>, C> type;
  type c1, c2;
public:
  int compare_variable; // ?
};
// the definition below should either go in a .cpp file,
// or you should mark it inline
bool A::C::operator()(A const &x, A const &y) {
  return x.compare_variable < y.compare_variable;
}