C++ 嵌套 类 是正确的封装方法吗?
Are C++ nested classes the right approach for encapsulation?
我有一个全局 class TRK
,它有很多成员和方法。我想通过将它们分类为不同的命名类别来组织它们,例如Fitting
,这样主 class 的命名空间就不会拥挤。在一个完美的世界中,我希望这个例子能够工作:
class TRK
{
public:
// constructors
TRK(...);
...
TRK();
~TRK();
// nested classes
class Fitting;
// and many other methods...
private:
...
};
class TRK::Fitting
{
public:
// constructors/destructor
TRK& trk;
Fitting();
~Fitting();
// and many other methods...
private:
...
};
我需要的关键是能够:
使用 TRK
class' 构造函数之一实例化一些 TRK
对象,我需要 TRK
构造函数也能够自动实例化伴随的嵌套 classes 例如Fitting
,对于 TRK
的实例。然后,我需要能够在 TRK
构造函数中将 instantiate/give 值赋给这些嵌套 classes 的成员。例如,如果 Fitting
有一些成员 x
,我需要能够在给定参数的情况下,在 TRK
构造函数中为该 TRK 实例初始化 x
的值给构造函数。我不清楚该怎么做;如何以及在哪里可以实例化这些嵌套的 classes?
从 TRK 实例和方法访问嵌套 classes 的成员,反之亦然。如图所示,我已经可以通过引用嵌套 classes 传递 TRK
来完成后者,但我不确定如何执行前者。
例如,我有 Fitting
的方法需要使用任何 TRK
实例的成员,Fitting
的实例是在其中创建的。同样,我有 Fitting
的方法,TRK
的方法需要能够调用。
我什至应该为此使用嵌套的 classes 吗?我尝试使用命名空间和继承,但我无法让事情按照我想要的方式工作。我的核心问题是尝试
构造嵌套实例 classes
如果你想让TRK
的构造函数依次引起TRK::Fitting
变量的构造,TRK::Fitting
的定义必须完全被它知道,前向声明是不够。但是,一旦这样做,就可以像往常一样初始化嵌套 class 类型的成员变量。这是一个例子:
class TRK {
class Fitting {
int x;
public:
Fitting(int x): x(x) {}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
};
嵌套 classes 访问父级 class
一个嵌套的class只是一个普通的class,只是它的名字是嵌套的。它不会自动知道父类的非静态成员变量在哪里。一个简单的解决方案是为嵌套 class 提供对父 class 实例的引用,如下所示:
class TRK {
class Fitting {
TRK &parent;
int x;
public:
Fitting(TRK &parent, int x): parent(parent), x(x) {}
void foo() {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(*this, y) {}
void bar() {}
};
另一种选择是不在子 class 中存储对父的引用,而是将对父的引用显式传递给子 class 的每个成员函数:
class TRK {
class Fitting {
void foo(TRK &parent) {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
void bar() {}
void quux() {
fitting.bar(*this);
}
};
从父 class 调用子 class 的成员函数很容易,如 TRK::quux()
.
所示
如果你想使用继承并且让基 class 能够调用派生 class 中的函数,那么可以使用 curiously recurring template pattern,像这样:
template <typename Derived>
class TRK {
...
void bar() {}
void quux() {
// We need to static_cast<> ourself to get an object of type Derived
static_cast<Derived>(*this)::foo();
}
};
class Derived: TRK<Derived> {
...
void foo() {
// We can directly call any base class member functions here
bar();
}
}
我有一个全局 class TRK
,它有很多成员和方法。我想通过将它们分类为不同的命名类别来组织它们,例如Fitting
,这样主 class 的命名空间就不会拥挤。在一个完美的世界中,我希望这个例子能够工作:
class TRK
{
public:
// constructors
TRK(...);
...
TRK();
~TRK();
// nested classes
class Fitting;
// and many other methods...
private:
...
};
class TRK::Fitting
{
public:
// constructors/destructor
TRK& trk;
Fitting();
~Fitting();
// and many other methods...
private:
...
};
我需要的关键是能够:
使用
TRK
class' 构造函数之一实例化一些TRK
对象,我需要TRK
构造函数也能够自动实例化伴随的嵌套 classes 例如Fitting
,对于TRK
的实例。然后,我需要能够在TRK
构造函数中将 instantiate/give 值赋给这些嵌套 classes 的成员。例如,如果Fitting
有一些成员x
,我需要能够在给定参数的情况下,在TRK
构造函数中为该 TRK 实例初始化x
的值给构造函数。我不清楚该怎么做;如何以及在哪里可以实例化这些嵌套的 classes?从 TRK 实例和方法访问嵌套 classes 的成员,反之亦然。如图所示,我已经可以通过引用嵌套 classes 传递
TRK
来完成后者,但我不确定如何执行前者。
例如,我有 Fitting
的方法需要使用任何 TRK
实例的成员,Fitting
的实例是在其中创建的。同样,我有 Fitting
的方法,TRK
的方法需要能够调用。
我什至应该为此使用嵌套的 classes 吗?我尝试使用命名空间和继承,但我无法让事情按照我想要的方式工作。我的核心问题是尝试
构造嵌套实例 classes
如果你想让TRK
的构造函数依次引起TRK::Fitting
变量的构造,TRK::Fitting
的定义必须完全被它知道,前向声明是不够。但是,一旦这样做,就可以像往常一样初始化嵌套 class 类型的成员变量。这是一个例子:
class TRK {
class Fitting {
int x;
public:
Fitting(int x): x(x) {}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
};
嵌套 classes 访问父级 class
一个嵌套的class只是一个普通的class,只是它的名字是嵌套的。它不会自动知道父类的非静态成员变量在哪里。一个简单的解决方案是为嵌套 class 提供对父 class 实例的引用,如下所示:
class TRK {
class Fitting {
TRK &parent;
int x;
public:
Fitting(TRK &parent, int x): parent(parent), x(x) {}
void foo() {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(*this, y) {}
void bar() {}
};
另一种选择是不在子 class 中存储对父的引用,而是将对父的引用显式传递给子 class 的每个成员函数:
class TRK {
class Fitting {
void foo(TRK &parent) {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
void bar() {}
void quux() {
fitting.bar(*this);
}
};
从父 class 调用子 class 的成员函数很容易,如 TRK::quux()
.
如果你想使用继承并且让基 class 能够调用派生 class 中的函数,那么可以使用 curiously recurring template pattern,像这样:
template <typename Derived>
class TRK {
...
void bar() {}
void quux() {
// We need to static_cast<> ourself to get an object of type Derived
static_cast<Derived>(*this)::foo();
}
};
class Derived: TRK<Derived> {
...
void foo() {
// We can directly call any base class member functions here
bar();
}
}