C++:将 this 指针传递给另一个 class
C++: passing the this pointer to another class
我是 C++ 的新手,但我在 Java 方面有一些经验。
在编码时,我偶然发现了一个让我困惑的错误。
这是我的代码(经过简化,但错误相同):
A.h:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp:
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h:
#pragma once
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B.cpp:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
我想将 a 对象的指针传递给 B[=50= 中的 bar 函数],这样我就可以修改和访问 a 在 bar 中的字段。奇怪的是,当我通过另一个 class:
的 A 实例调用 foo 时出现这些错误
1>------ Build started: Project: Test, Configuration: Debug Win32 ------
1> main.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1> B.cpp
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C3646: 'b': unknown override specifier
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1> A.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1>d:\stuff\visual studio 2015\projects\test\test\a.cpp(5): error C2660: 'B::bar': function does not take 1 arguments
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
如果我不在 B.h 中包含 A.h 并且我不包含,则代码可以正常工作不要将任何东西传递给 bar 函数。
我尝试 google 是什么导致了这些错误,但我无法自行解决问题,因为我不明白是什么导致了这些错误。我做错了什么?
在A.h的头文件中,你有:
#include "B.h"
在B.h的头文件中,你有:
#include "A.h"
您有一个循环包含,其中 A
和 B
的定义相互依赖。
一个简单的解决方案是在 class B
的定义中使用 forward declaration:
- 将文件 B.h 中的行
#include "A.h"
替换为 class B;
- 在B.cpp
开头添加#include "A.h"
但是请注意,您不能对 class A
使用前向声明,原因是您将 class B
的值 b
作为 class A
的成员变量:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b; /// I mean this line here more specifically
};
编译器需要知道 class B
的定义,以便为 class A 确定正确的大小。这就是为什么你必须将 #include "B.h"
放在最开始的原因A.h。
两个 header 都在互相引用。只有一个可以真正首先被编译器求值,并且那个不能解析对另一个 header 中的 class 的引用。错误并不明显,但是 "once" #pragma 使 header 中的一个包含没有如您预期的那样发生。
如果 B.h header 文件不需要知道 A class 的实现细节,在这种情况下它不需要,那么不要包含 A.h 文件在 B.h 中。相反,将 bar() 的函数声明更改为如下所示:
bar( class A *a );
编译器可以由此构建代码,将指针传递给 A object,而无需了解 A 内部的内容。它不需要 A.h header .
然后在B.cpp中的B.hheader文件之后包含A.hheader文件。
我测试了这个,它对我有用。
让我们看一下 B.cpp,看看包含的内容会发生什么:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
粘贴 B.h 代替包含,我们得到:
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
然后放置 A.h 代替它的包含:
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
我们在这里停止,因为 pragma once
阻止重新包含 B.h
我们可以看到在classA
的定义中我们有B b;
,但是classB
还没有定义。轰隆隆。 A
不能在没有 B
的情况下定义,并且 B
尚未定义。
A
必须有B
的大小才能满足B b;
,所以需要B
的完整定义。 B
只需要知道A
存在,因为它只需要一个指向A
的指针就可以满足void bar(A *a);
。所以...
A.h
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h
#pragma once
class A; // forward definition of class A
class B
{
public:
B();
void bar(A *a);
};
B.cpp
#include "A.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
做这些改变:
B.h: - 转发声明 A
#pragma once
// #include "A.h"
class A;
//^^^^^^
class B {
public:
B();
void bar(A *a);
};
B.cpp: #include "A.h"
//#include "B.h"
#include "A.h"
//^^^^^^^^^^^^
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
就是这样。
我是 C++ 的新手,但我在 Java 方面有一些经验。 在编码时,我偶然发现了一个让我困惑的错误。 这是我的代码(经过简化,但错误相同):
A.h:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp:
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h:
#pragma once
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B.cpp:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
我想将 a 对象的指针传递给 B[=50= 中的 bar 函数],这样我就可以修改和访问 a 在 bar 中的字段。奇怪的是,当我通过另一个 class:
的 A 实例调用 foo 时出现这些错误1>------ Build started: Project: Test, Configuration: Debug Win32 ------
1> main.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1> B.cpp
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C3646: 'b': unknown override specifier
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1> A.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1>d:\stuff\visual studio 2015\projects\test\test\a.cpp(5): error C2660: 'B::bar': function does not take 1 arguments
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
如果我不在 B.h 中包含 A.h 并且我不包含,则代码可以正常工作不要将任何东西传递给 bar 函数。
我尝试 google 是什么导致了这些错误,但我无法自行解决问题,因为我不明白是什么导致了这些错误。我做错了什么?
在A.h的头文件中,你有:
#include "B.h"
在B.h的头文件中,你有:
#include "A.h"
您有一个循环包含,其中 A
和 B
的定义相互依赖。
一个简单的解决方案是在 class B
的定义中使用 forward declaration:
- 将文件 B.h 中的行
#include "A.h"
替换为class B;
- 在B.cpp 开头添加
#include "A.h"
但是请注意,您不能对 class A
使用前向声明,原因是您将 class B
的值 b
作为 class A
的成员变量:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b; /// I mean this line here more specifically
};
编译器需要知道 class B
的定义,以便为 class A 确定正确的大小。这就是为什么你必须将 #include "B.h"
放在最开始的原因A.h。
两个 header 都在互相引用。只有一个可以真正首先被编译器求值,并且那个不能解析对另一个 header 中的 class 的引用。错误并不明显,但是 "once" #pragma 使 header 中的一个包含没有如您预期的那样发生。
如果 B.h header 文件不需要知道 A class 的实现细节,在这种情况下它不需要,那么不要包含 A.h 文件在 B.h 中。相反,将 bar() 的函数声明更改为如下所示:
bar( class A *a );
编译器可以由此构建代码,将指针传递给 A object,而无需了解 A 内部的内容。它不需要 A.h header .
然后在B.cpp中的B.hheader文件之后包含A.hheader文件。
我测试了这个,它对我有用。
让我们看一下 B.cpp,看看包含的内容会发生什么:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
粘贴 B.h 代替包含,我们得到:
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
然后放置 A.h 代替它的包含:
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
我们在这里停止,因为 pragma once
阻止重新包含 B.h
我们可以看到在classA
的定义中我们有B b;
,但是classB
还没有定义。轰隆隆。 A
不能在没有 B
的情况下定义,并且 B
尚未定义。
A
必须有B
的大小才能满足B b;
,所以需要B
的完整定义。 B
只需要知道A
存在,因为它只需要一个指向A
的指针就可以满足void bar(A *a);
。所以...
A.h
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h
#pragma once
class A; // forward definition of class A
class B
{
public:
B();
void bar(A *a);
};
B.cpp
#include "A.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
做这些改变:
B.h: - 转发声明 A
#pragma once
// #include "A.h"
class A;
//^^^^^^
class B {
public:
B();
void bar(A *a);
};
B.cpp: #include "A.h"
//#include "B.h"
#include "A.h"
//^^^^^^^^^^^^
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
就是这样。