在 C++ 中使用前向声明的错误
Errors using forward declaration in c++
我正在尝试用 c++ 编写一个简单的程序,我有 2 个 类,两者都可以相互访问函数。这是我最终实际尝试做的事情的简化,即创建一个棋盘游戏 类。我能够在 java 中做到这一点,但我现在 运行 遇到了问题,试图在 C++ 中做同样的事情。我的代码如下:
#include <iostream>
class B;
class A {
public:
void sync(B obj){
b = obj;
}
void print(){
std::cout << "Hello from class A" << std::endl;
}
void printBoth(){
std::cout << "Hello from class A" << std::endl;
b.print();
}
private:
B b;
};
class B {
public:
B(A obj){
a = obj;
}
void print(){
std::cout << "Hello from class B" << std::endl;
}
void printBoth(){
std::cout << "Hello from class B" << std::endl;
a.print();
}
private:
A a;
};
int main(){
A a;
B b(a);
a.sync(b);
a.printBoth();
std::cout << std::endl;
b.printBoth();
return 0;
}
当我尝试用 g++ example.cpp
编译它时,我收到 5 个错误:
example.cpp:20:5: error: field ‘b’ has incomplete type
B b;
^
example.cpp: In member function ‘void A::sync(B)’:
example.cpp:7:8: error: ‘obj’ has incomplete type
void sync(B obj){
^
example.cpp:3:7: error: forward declaration of ‘class B’
class B;
^
example.cpp:8:4: error: ‘b’ was not declared in this scope
b = obj;
^
example.cpp: In member function ‘void A::printBoth()’:
example.cpp:17:4: error: ‘b’ was not declared in this scope
b.print();
^
我从未在 类 中使用过前向声明,所以如果我遗漏了一些明显的东西,我深表歉意。感谢您的帮助,在此先感谢您。
你的代码有两个问题。
我们来看第一个问题。
下面是两个 class 具有相互调用方法的示例。毫无意义,并导致无限循环,但这演示了前向声明的一般原则,您可以将其用作模板来修复您显示的代码。
class A {
public:
void foo();
};
class B {
public:
void foo();
};
void A::foo()
{
B b;
b.foo();
}
void B::foo()
{
A a;
a.foo();
};
现在,您的代码存在第二个问题:
正如所写,您的 class A 包含 class B 的实例,其中包含 class A 的实例,其中包含 class A 的实例,其中包含 class B 的一个实例,一直到宇宙在一个巨大的黑洞中内爆。可以说,这不会编译。
C++ 对象从根本上不同于 Java 对象。他们以完全不同的方式工作。您可以在 Java 中执行此操作,因为肮脏的小秘密是 Java 中的所有对象实际上都是海市蜃楼,它们实际上是指向实际对象的引用计数指针。在 C++ 中,最接近的等效项是向对象声明一个 std::shared_ptr
:
#include <memory>
class A;
class B;
class A {
// ...
private:
std::shared_ptr<B> b;
};
class B {
// ...
private:
std:shared_ptr<A> a;
};
这将是您显示的代码的第二个问题。通常,在学习 C++ 对象时,您需要几乎忘记所有关于 Java 对象的知识。它们本质上是不同的,并且尝试在您已经了解的 Java 对象和 C++ 对象之间始终如一地进行类比只会导致混淆。
您可以随时尝试重新设计,即:
#include <iostream>
#include "A.hpp"
int main(){
A a;
B b(a);
a.sync(b);
a.printBoth();
std::cout << std::endl;
b.printBoth();
return 0;
}
B.hpp:
class A;
class B {
public:
B() {}
B(A obj);
void print();
void printBoth();
private:
A* a;
};
B.cpp:
#include <iostream>
#include "A.hpp"
B::B(A obj){
a = new A(obj);
}
void B::print(){
std::cout << "Hello from class B" << std::endl;
}
void B::printBoth(){
std::cout << "Hello from class B" << std::endl;
a->print();
}
A.hpp:
#include "B.hpp"
class A {
public:
void sync(B obj);
void print();
void printBoth();
private:
B b;
};
A.cpp:
#include <iostream>
#include "A.hpp"
void A::sync(B obj){
b = obj;
}
void A::print(){
std::cout << "Hello from class A" << std::endl;
}
void A::printBoth(){
std::cout << "Hello from class A" << std::endl;
b.print();
}
我正在尝试用 c++ 编写一个简单的程序,我有 2 个 类,两者都可以相互访问函数。这是我最终实际尝试做的事情的简化,即创建一个棋盘游戏 类。我能够在 java 中做到这一点,但我现在 运行 遇到了问题,试图在 C++ 中做同样的事情。我的代码如下:
#include <iostream>
class B;
class A {
public:
void sync(B obj){
b = obj;
}
void print(){
std::cout << "Hello from class A" << std::endl;
}
void printBoth(){
std::cout << "Hello from class A" << std::endl;
b.print();
}
private:
B b;
};
class B {
public:
B(A obj){
a = obj;
}
void print(){
std::cout << "Hello from class B" << std::endl;
}
void printBoth(){
std::cout << "Hello from class B" << std::endl;
a.print();
}
private:
A a;
};
int main(){
A a;
B b(a);
a.sync(b);
a.printBoth();
std::cout << std::endl;
b.printBoth();
return 0;
}
当我尝试用 g++ example.cpp
编译它时,我收到 5 个错误:
example.cpp:20:5: error: field ‘b’ has incomplete type
B b;
^
example.cpp: In member function ‘void A::sync(B)’:
example.cpp:7:8: error: ‘obj’ has incomplete type
void sync(B obj){
^
example.cpp:3:7: error: forward declaration of ‘class B’
class B;
^
example.cpp:8:4: error: ‘b’ was not declared in this scope
b = obj;
^
example.cpp: In member function ‘void A::printBoth()’:
example.cpp:17:4: error: ‘b’ was not declared in this scope
b.print();
^
我从未在 类 中使用过前向声明,所以如果我遗漏了一些明显的东西,我深表歉意。感谢您的帮助,在此先感谢您。
你的代码有两个问题。
我们来看第一个问题。
下面是两个 class 具有相互调用方法的示例。毫无意义,并导致无限循环,但这演示了前向声明的一般原则,您可以将其用作模板来修复您显示的代码。
class A {
public:
void foo();
};
class B {
public:
void foo();
};
void A::foo()
{
B b;
b.foo();
}
void B::foo()
{
A a;
a.foo();
};
现在,您的代码存在第二个问题:
正如所写,您的 class A 包含 class B 的实例,其中包含 class A 的实例,其中包含 class A 的实例,其中包含 class B 的一个实例,一直到宇宙在一个巨大的黑洞中内爆。可以说,这不会编译。
C++ 对象从根本上不同于 Java 对象。他们以完全不同的方式工作。您可以在 Java 中执行此操作,因为肮脏的小秘密是 Java 中的所有对象实际上都是海市蜃楼,它们实际上是指向实际对象的引用计数指针。在 C++ 中,最接近的等效项是向对象声明一个 std::shared_ptr
:
#include <memory>
class A;
class B;
class A {
// ...
private:
std::shared_ptr<B> b;
};
class B {
// ...
private:
std:shared_ptr<A> a;
};
这将是您显示的代码的第二个问题。通常,在学习 C++ 对象时,您需要几乎忘记所有关于 Java 对象的知识。它们本质上是不同的,并且尝试在您已经了解的 Java 对象和 C++ 对象之间始终如一地进行类比只会导致混淆。
您可以随时尝试重新设计,即:
#include <iostream>
#include "A.hpp"
int main(){
A a;
B b(a);
a.sync(b);
a.printBoth();
std::cout << std::endl;
b.printBoth();
return 0;
}
B.hpp:
class A;
class B {
public:
B() {}
B(A obj);
void print();
void printBoth();
private:
A* a;
};
B.cpp:
#include <iostream>
#include "A.hpp"
B::B(A obj){
a = new A(obj);
}
void B::print(){
std::cout << "Hello from class B" << std::endl;
}
void B::printBoth(){
std::cout << "Hello from class B" << std::endl;
a->print();
}
A.hpp:
#include "B.hpp"
class A {
public:
void sync(B obj);
void print();
void printBoth();
private:
B b;
};
A.cpp:
#include <iostream>
#include "A.hpp"
void A::sync(B obj){
b = obj;
}
void A::print(){
std::cout << "Hello from class A" << std::endl;
}
void A::printBoth(){
std::cout << "Hello from class A" << std::endl;
b.print();
}