我正在将旧的c ++程序转换为OOP,随着事情变得越来越大,我在.h和.cpp文件中按类拆分它。第一个类很好地编译成目标文件。但我的第二堂课依赖于头等舱,现在我遇到了问题。这里我的非常简化的“所有单个文件”代码有效:
class A {
public:
void amethod(int) {
....code....
}
};
A a_obj; //object creation
class B {
public
void bmethod(void) {
a_obj.amethod(int);
}
};
B b_obj; //object creation
main() {
b_obj.bmethod();
}
将代码分配到不同的文件后,我的.h文件看起来像:
//file A.h:
class A {
public:
void amethod(int);
};
//file B.h
#include "A.h"
class B {
public
void bmethod(void);
};
在B类的实现中,有对a_obj.amethod()的调用,甚至我理解g ++无法知道a_obj是A类的对象,因为我甚至没有包含在任何地方创建的a_obj对象代码。
如何解决这个问题?我需要将对象创建放在我的.h或.cpp文件中(注意很多其他类正在使用相同的amethod())这是一件简单的事情。我不能让所有东西都是静态的,因为我也有多个对象的类(事实上,整个程序的工作方式相同)。或者这种工作方式完全错误(这可以解释为什么我找不到任何解决方案)。
答案 0 :(得分:1)
建议您加大力度来定义界面。
如果班级B
需要A
的实例才能使用,请使用参数传递A
:
class B {
public
void bmethod(A & a_obj) {
a_obj.amethod(int);
}
};
main() {
A a_obj;
B b_obj;
b_obj.bmethod(a_obj);
}
答案 1 :(得分:0)
问题是您的原始代码使用全局数据(即a_obj
和b_obj
的声明是全局的)。全局通常是一个坏主意,因为它们可能会导致一些问题。 “正确”的OOP方法是在main()
中实例化这些对象,并将它们传递给任何其他需要访问它们的对象。您可以根据需要传递引用,指针或副本。
话虽如此,如果确实希望继续使用全局数据,那么您可以使用extern
声明。在您访问a_obj
的每个* .cpp文件中,包含以下内容:
extern A a_obj;
这基本上告诉编译器有一个具有该名称的对象,但它存在于其他地方。如果你认真学习OOP,我真的不推荐这种方法。
答案 2 :(得分:0)
我猜你打算在其他实现文件(.cpp)中使用a_obj作为全局变量。 所以在头文件B.h中输入对此实例的extern引用。
extern A a_obj;
此声明应该有助于编译B.cpp文件。并在链接期间询问实际实例a_obj。 我没有尝试这个代码,但是根据我的经验和我的编码实践(方式)来讲述。希望这个解决方案有所帮助,否则很抱歉。
答案 3 :(得分:0)
首先,为了调用A :: amethod(),B类需要A类及其amethod()的完整定义。所以你需要在.cpp文件中的B.h之前#include A.h。
接下来,如果您处理具体的a_obj对象,则需要指定该对象的内容才能正确链接。在你的第一个变体中它是全局对象,所以如果它是你想要写的东西:在A.cpp中:
A a_obj;
在B.cpp:
extern a_obj;
// here you can call a_obj methods
但是如果这些类是如此相关,以至于一个人调用另一个的方法,而且当我抓住你需要A和B的几个对象时,考虑通过继承来连接这些类:
class B : public A {
public:
void bMethod(int n) {
aMethod(n); // base class method call
}
// ...
或通过授权:
class B {
A m_A;
public:
void bMethod(int n) {
m_A.aMethod(n);
}
// ...
正如前面提到的那样
void bMethod(A& a) {
a.aMethod();
}
会起作用,但语言有内置的方法来表达类关系。
如何实现更多的设计问题,你可以在Stroustrup第3版,'24 .3.5使用关系'中阅读更多相关内容。
在C ++中,您还可以将指向一个类的成员函数的指针传递到另一个类的成员函数中,以从完全不相关的类调用方法(比如一些回调),您可以使用boost::function和{ {3}}为此。但它是先进的技术。