不能使外部类成为内部类内的成员对象
cannot make outer class as member object inside inner class
我对以下代码有 3 个问题:
class cb
{
public:
int y_;
class iterator
{
public:
//void func() { y_ = 5; } // (1)
private:
int x_;
//cb a; // (2)
};
void funcCB() { }
};
class Human
{
public:
void func() const {
cb c; // (3)
c.funcCB();
}
// (4)
};
1-为什么我不能像(1)那样在内部类内部使用外部类的成员变量y_
?
2-为什么我不能像in(2)那样从内部类的外部类创建对象,而只能创建指针和引用?
3-为什么如果我将(3)处的行移动到(4cb c;
)处的行,则会出现编译错误?
- 您不能使用外部类字段,因为它不像您的类迭代器可以直接访问它。首先,您为什么要访问该字段?我会考虑先重新设计您的解决方案。但正如你所愿,这里是你可以做些什么来解决这个问题。您需要引用作为您的父对象的对象
class cb
{
public:
cb(): it(*this) {} // Passing the reference to ourself for iterator object init to have access in iterator class access to y_ field.
int y_;
class iterator
{
public:
iterator(cb& ob): a(ob) {}
void func() { a.y_ = 5; }
private:
int x_;
cb& a; // Reference to parent object
};
iterator it; // Added because I don't see the point where you don't want to have that object in your cb class.
void funcCB() { }
};
我不确定你想在这里实现什么。它将抛出不完整的类型,因为您将想要创建 cb 对象,您将在其中创建迭代器对象,您将在其中创建 cb 对象,您将在其中再次创建迭代器,以便获得无限递归(如果我理解正确的话)。当您将迭代器指向具体对象时,它将停止循环。
您应该将类 cb funcCB 更改为调用 funcCB(),它不会修改来自 Human 类的对象 c,并且限定符之间存在差异,因为在这种情况下您没有const 函数。您还可以在 Human类中删除 func 的 const 限定符,这也将起作用。当您不更改限定符时,这里会发生错误,因为当您有 const 函数在其中创建一些对象以进一步使用时,以及当您将对象作为类字段并且您调用无法更改 Human 类和 CB 类的状态的函数时,情况会有所不同funcCB 没有等效的 const 函数。
void funcCB() const {}
,因为否则在类 Human 中可以理解,在 func() 中,这是 const 函数,您想为什么我不能像 (1) 那样在内部类内部使用外部类的成员变量y_?
因为y_
是类cb
的非静态数据成员,这意味着我们必须在特定cb
对象上访问它。但问题来了。赋值语句y_ = 5;
等效于:
vvvv--------------->this points to an object of type iterator and not cb
this->y_ = 5;
在上面显示的等效语句中,this
指针指向类型为iterator
的当前实例,而不是cb
。但是由于要访问y_
我们必须使用cb
类型对象,因此我们得到了提到的错误。
基本上y_
应该在类型为cb
的对象上访问。例如,您可以func
具有类型为cb&
的参数,然后访问y_
如下所示:
class cb
{
public:
int y_;
class iterator
{
public:
//------------vvv------------------->pass object of type cb by reference
void func(cb& it) { it.y_ = 5; } // (1) OK NOW
//----------------------^^---------->access member y_ on object it
private:
int x_;
};
void funcCB() { }
};
为什么我不能像 in(2) 一样从内部类的外部类创建对象,但我只能创建指针和引用?
因为在#2
点,类cb
不完整,因此在第#2
点我们无法创建类型为cb
的非静态数据成员。这可以从完整的类型文档中看出,其中指出:
以下任何上下文都需要类型
T
才能完成:
- 声明类型
T
的非静态类数据成员;
这意味着在第#2
点,我们不能为类型cb
的非静态数据成员提供声明,但我们仍然可以为cb&
或cb*
类型的非静态数据成员提供声明,因为我们可以有一个指针或对不完整类型的引用,如cb
.
为什么如果我在 (3)
cb c
处移动行; 在 (4) 处移动行我得到编译错误?
如果将第#3
行 (cb c;
) 移动到第#4
行,则不会收到任何编译时错误。演示
class Human
{
public:
void func() const {
//cb c; // (3)
//c.funcCB();
}
cb c; // (4) perfectly fine
};
如果我不太明白这一点,请原谅我 - 我的C++有点生锈。
关于问题(1)——你试过"这个"关键词吗?
例如:
void func() { this->y_ = 5; }
这是一个与您的示例几乎相同的示例:
C++中的"this"指针
对于问题 2,您要求递归包含对象。这就像在说,什么是洋葱?这是一个含有洋葱的果皮。嗯,里面的洋葱也是一个皮,里面有一个洋葱,然后是一个皮,然后是一个洋葱,等等。如果没有一些停止机制(洋葱可能是一个核心,它不包含任何东西),洋葱对象的第一个实例化将无限循环,直到所有内存都用完。
作为参考,内存只能在需要时检索,而不是之前检索。
对于问题3,我懒惰地说,他们只是规则。
更新:我现在不在工作,所以我有更多的时间做更多的研究。正如我所说,我的C++有点生锈。
本质上,对于问题 1,您尝试做的是从类"迭代器"访问类"cb"的成员。我的研究表明,仅仅因为"迭代器"是"cb"的一个子类,它就没有任何特殊的访问权限。因此,您不能从"迭代器"访问"cb::y_",也不能使用"this->y_"。类内的方法(函数)可以直接访问"y_"。子类不能。
请注意以下成功编译
:class cb {
public:
int y_;
class iterator {
public:
void func() {
cb *z = new cb();
z->y_ = 5;
} // (1)
private:
int x_;
cb *a; // (2)
};
void funcCB() { }
};
class Human
{
public:
void func() const {
cb c; // (3)
c.funcCB();
}
// (4)
cb *z;
};
这可能不是你想要完成的,但我希望你想做的事情不能按照你想要的方式完成。最好的办法是将"迭代器"实现为与"cb"不同的自己的类,并使其成为"cb"的"友元"类。或者也许更好,更简单,只需在类中包含一组迭代器方法。这些方法将具有对所有类属性的完全访问权限。
另请注意指针对"cb"的引用。它不会编译为子类中的直接对象实例化。再次,洋葱问题。
附带说明一下,请记住C++不是帕斯卡。它不是Java。它可以做子类,但正如你所看到的,它不能很好地做它们,或者至少,它不像其他语言那样做它们。您最好创建与其他类完全不同的每个类,而不是正常的继承。这有点非正式的"C++之道"。
- 从模板化父类中的派生内部类访问受保护的成员变量
- 如何使用包含内部类的类实例有效地从内部类访问成员?
- (2 问题)"类"类型重新定义(即使 #pragma 一次),以及静态函数内的静态成员对象初始化?
- 如何在没有setter的情况下设置类内部类的成员变量?
- 内部类私有成员访问和封闭的友好性
- 在C++中从内部类对象获取外部类对象
- 从内部类访问外部公共成员
- C++ 将成员函数指针传递给内部类
- 不能使外部类成为内部类内的成员对象
- clang或gcc关于这个内部类成员访问是否正确
- 如何在声明时间内启动成员对象
- 我想在C++中创建内部类的对象,或者可能是嵌套类
- 在命名空间中,如何定义从内部类返回对象的函数
- 在C++调用内部类成员的情况下,是否应使用此 -> 运算符?
- 无法使用外部类对象访问内部类成员
- 创建模板内部类的对象
- 使用(非类型)枚举参数定义内部类成员函数模板
- C++:初始化英特尔SIMD内部类成员
- 无法初始化内部类的对象C++
- 如何在派生类中定义内部类成员