【C++进阶】类别互相引用(Class include each other)

[C/C++]類別互相引用(Class include each other)


前言


最近開始久違的寫C++程式,然後因為物件上的關係,所以某個A類別會擁有B類別,同時B類別會需要知道A類別

為了能夠壤兩個類別都能夠看到,所以依照直覺的想法,會使兩方的標頭檔(Header file)都會Include彼此,但是此時編譯器卻會發生問題,究竟是為什麼呢? 這樣的想法不是很合理嗎? 

但其實編譯器在解讀時是會出現問題的,究竟哪裡有問題?

經過朋友的解說後,解決了問題也知道了原因,這邊來介紹一下給需要知道的人。

類別互相引用


有時候在開發物件導向的程式時,免不了因為一些OO關係,需要讓某個A類別會擁有B類別,同時B類別會需要知道A類別:

標頭檔互相引用的錯誤的原因


這邊我們拿A與B類別來解釋,前面提到「A類別會擁有B類別,同時B類別會需要知道A類別」,因為擁有B,所以需要include B,而B因為知道A,貌似直覺的做法B也會include A,此時在編譯的程序就會變成:

A class -> A Include B-> 進入B class -> B include A -> A class

所以會再次去A class的標頭檔(如下程式碼)

A.h

#ifndef A_H
#define A_H

#include "B.h"

class A
{
public:
	A(void);
	~A(void);
private:
	B b;
};

#endif

B.h

#ifndef B_H
#define B_H

#include "A.h"

class B
{
public:
	B(void);
	~B(void);
private:
	A *a; 
};

#endif

依照常理來說,一般我們在寫標頭檔時,會使用 #ifndef 、#define、#endif的前置處理指令,確保只會被編譯過一次,之後被include多次時,不會再被編譯:

#ifndef A_H
#define A_H

class A{
 //....
}

#endif

但是問題卻來,編譯時編譯A檔案,此發實現include B,便跳至B檔案,卻又發現B檔案有include A,再次跳回A檔案時,卻會因為A檔案先前編譯時,因為有加入#ifndef A_H與#define A_H的關係,定義過A_H,便不會再往下編譯A class,因此而又跳回B檔案,造成B檔案不認識A Class而在編譯其出錯。

但是,其實我們的B Class只是知道A(pointer)而已,根本不需要include A.h

解決方式-前置宣告(Forward Declartion)


我們可以透過前至宣告的方式來告訴編譯器「先知道這個class的存在,至於他的定義後面會說明」。

只要不涉及生成或操作的話,前至宣告可以用在指標或參考類別。

然後再.cpp檔實際操作時,在include 類別標頭檔:

A.h

#ifndef A_H
#define A_H

#include "B.h"

class A
{
public:
	A(void);
	~A(void);
private:
	B b;
};

#endif

A.cpp

#include "A.h"


A::A(void)
{
}


A::~A(void)
{
}

B類別稍微修改一下:

B.h

#ifndef B_H
#define B_H

class A;

class B
{
public:
	B(void);
	~B(void);
private:
	A *a; 
};

#endif

在cpp檔中,我們在來incldue A.h檔

B.cpp

#include "B.h"
#include "A.h"

B::B(void)
{
}


B::~B(void)
{
}

以上的原因與解決方式,希望可以幫助到遇到此問題的人可以解惑!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sure, I'd be happy to help you with that! Here's a sample code for defining a units class in C++ that can be used to perform basic engineering problems: ```c++ #include <iostream> #include <string> using namespace std; class Units { private: double value; string unit; public: Units(double v, string u) { value = v; unit = u; } double getValue() { return value; } string getUnit() { return unit; } void setValue(double v) { value = v; } void setUnit(string u) { unit = u; } void convert(string newUnit) { // Define conversion factors for each unit double factor = 1.0; if (unit == "m" && newUnit == "cm") { factor = 100.0; } else if (unit == "cm" && newUnit == "m") { factor = 0.01; } else if (unit == "kg" && newUnit == "g") { factor = 1000.0; } else if (unit == "g" && newUnit == "kg") { factor = 0.001; } // Convert value to new unit value *= factor; unit = newUnit; } Units operator+(const Units& other) { if (unit != other.unit) { cout << "Error: units are not compatible!" << endl; return *this; } double newValue = value + other.value; return Units(newValue, unit); } Units operator-(const Units& other) { if (unit != other.unit) { cout << "Error: units are not compatible!" << endl; return *this; } double newValue = value - other.value; return Units(newValue, unit); } }; int main() { Units length(1.0, "m"); length.convert("cm"); cout << length.getValue() << " " << length.getUnit() << endl; Units mass1(1.0, "kg"); Units mass2(2.0, "g"); Units totalMass = mass1 + mass2; cout << totalMass.getValue() << " " << totalMass.getUnit() << endl; Units error = length + mass1; cout << error.getValue() << " " << error.getUnit() << endl; return 0; } ``` In this code, the `Units` class has two private member variables: `value` and `unit`. The constructor initializes these variables with the provided values. The class also has various public member functions, such as `getValue()`, `getUnit()`, `setValue()`, `setUnit()`, `convert()`, and overloaded operators `+` and `-`. The `convert()` function converts the unit of the `Units` object to a new unit, based on predefined conversion factors. The `+` and `-` operators allow the addition and subtraction of `Units` objects, respectively, as long as their units are compatible. In the `main()` function, we create various `Units` objects and perform some basic operations with them, such as unit conversion and addition/subtraction. Note that attempting to add or subtract `Units` objects with incompatible units will result in an error message.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值