01 C++中complex.h头文件的写法

1. 引言

本系列内容主要是介绍C++的学习笔记。第一部分01介绍不包含指针的头文件complex.h的写法以及使用,即用C++编写一个数学中复数的头文件,运用类构造、函数构造、运算符重载等实现在对复数的数学计算。

2. complex.h头文件的编写

1)头文件使用防卫式声明结构

#ifndef __COMPLEX__
#define  __COMPLEX__

//该部分为复数类结构定义内容

#endif //__COMPLEX__
说明:若有多个程序使用到头文件时会更加方便,通过头文件ifndef判断,编译器不会出现重复编译;

2)定义头文件中复数类complex的结构

#ifndef __COMPLEX__
#define __COMPLEX__

class complex;
complex&
__doapl(complex * ths, const complex& r);
complex&
__doami(complex * ths, const complex& r);
complex&
__doaml(complex * ths, const complex& r);
complex&
__doadv(complex * ths, const complex& r);

class complex
{
public:
	complex(double r = 0, double i = 0) :re(r), im(i){ }; //构造函数
	complex& operator += (const complex&);
	complex& operator -= (const complex&);
	complex& operator *= (const complex&);
	complex& operator /= (const complex&);
	//complex operator - (const complex&);

	double real() const { return re; }
	double imag() const { return im; }

private:
	double re, im;

	friend complex& __doapl(complex *, const complex&);
	friend complex& __doami(complex *, const complex&);
	friend complex& __doaml(complex *, const complex&);
	friend complex& __doadv(complex *, const complex&);
};
注意点:

a. 构造函数

对复数中实部和虚部的赋初值采用冒号后面赋值结构;

b. 传参类型和返回值类型

对于函数中的参数传递和返回值传递能用引用类型尽量传引用(通常传引用内存所占的字节较小,速度快),即C++中在参数后面加和字符&;

C++中详细引用的用法,我查找了网上相关资料,如http://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html

因传引用后,传的是地址,所以被传对方若修改内容则原对象也会改变。因此,若传入的参数不会改变,则在函数传递参数前加const来防止修改自己(修改后编译器会报错);

c. 成员函数和非成员函数

成员函数中有隐藏的this,而成员函数中没有。也就是说在使用成员函数中可以通过this的传入来表示这个传入的类;

任何操作都可以有两种写法,不一定是谁好谁坏。而<< 操作符,只能是非成员函数的写法。

d. 操作符重载

C++中操作符(operator +=)就是函数,可以重新设定;

在复数类complex中通过成员函数实现+=,-=等操作符对复数的操作,+=操作符包括+=右边和左边两部分操作数据,传入参数显示的只是右边复数常引用,实际上此时还包含左边传入复数的本身。

e. 内联函数

在复数类内实现的函数如real() 、imag()函数默认是内联函数,处理速度快(但函数实际是不是内联要看编译器的情况,一般函数复杂,编译器就不会识别为内联)。

f. 友元的作用

在类结构中函数使用friend关键字即友元,在使用时,友元对象可以自由取得类中private成员;

记住相同class的各个objects互为友元。

3)实现部分对复数运算符的操作

inline double
real(const complex& x)
{//1取实部
	return x.real();
}

inline complex&
__doapl(complex * ths, const complex& r)
{//2实现运算符+=操作
	ths->re += r.re;
	ths->im += r.im;
	return *ths;
}

inline complex&
complex::operator += (const complex& r)
{//3运算符+=操作
	return __doapl(this, r);
}

inline complex
operator + (const complex& x, const complex& y)
{//4实现运算符+操作
	return complex(real(x) + real(y), imag(x) + imag(y));
}

inline complex
conj(const complex& x)
{//5实现共轭复数操作
	return complex(real(x), -imag(x));
}

inline bool
operator == (double x, const complex& y)
{//6实现操作符==操作
	return x == real(y) && 0 == imag(y);
}

注意点:

a. 使用inline关键字

在类外部实现的成员函数和非成员函数前加inline,就是告诉编译器如果能实现inline就inline的方式,也就是内联函数;

b. 函数3运算符+=操作

函数3中就运用了关键字this,因为函数3是成员函数的实现。如对复数+=操作:c1 += c2,c1的地址传入就是表示this。最后通过函数2返回*ths来返回c1值本身,在整个过程中c1的存储位置不会变;

函数2之所以能以引用类型接收,一方面是*ths返回值是内存已经存在,不是local object创建的;令一方面虽然传递的是值类型而用引用接收,是因为传递者无需知道接收者是以引用形式接收。

c. 函数4实现运算符+操作

函数4的返回类型是complex,而不是引用。此时,也只能是complex类型。因为,实现+是在内存中重新创建一个complex对象(即local object),返回引用后原创建对象会失效。

3. 在主程序中实现对头文件的操作
// complex_cPP.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include "complex.h"
using namespace std;

ostream&
operator << (ostream& os, const complex& x)
{
	return os << "(" << real(x) << "," << imag(x) << ")";
}

int _tmain(int argc, _TCHAR* argv[])
{
	complex c1(4, 1);
	complex c2(4, 1);
	complex c3(2, 3);
	complex c4(4, 1);
	complex c5(2, 3);
	complex c6(4, 1);
	complex c7(2, 3);
	complex c8(4, 1);
	complex * c0 = new complex(2, 1);
	
	cout << 12 << endl;
	cout << "c0= " << *c0 << endl;
	cout << "c1 = " << c1 << endl;
	cout << "c2 = " << c2 << endl;
	cout << "c3 = " << c3 << endl;
	cout << "c4 = " << c4 << endl;
	cout << "c5 = " << c5 << endl;
	cout << "c6 = " << c6 << endl;
	cout << "c7 = " << c7 << endl;
	cout << "c8 = " << c8 << endl;

	//cout << "c1 += c2 => " << (c1 += c2) << endl;
	//cout << "c3 -= c4 => " << (c3 -= c4) << endl;
	//cout << "c5 *= c6 => " << (c5 *= c6) << endl;
	//cout << "c7 /= c8 => " << (c7 /= c8) << endl;

	//cout << c1 + c2 << endl;
	//cout << c1 + 5.0 << endl;
	//cout << 6.0 + c1 << endl;

	//cout << "c1 - c2 = " << (c1 - c2) << endl;
	//cout << "5 - c1 = " << (5 - c1) << endl;
	//cout << "c1 - 5 = " << (c1 - 5) << endl;

	//cout << "c1 * c2 = " << (c1 * c2) << endl;
	//cout << "5 * c1 = " << (5 * c1) << endl;
	//cout << "c1 * 5 = " << (c1 * 5) << endl;

	//cout << "c1 / c2 = " << (c1 / c2) << endl;
	//cout << " c1 / 5 = " << (c1 / 5) << endl;
	
	//cout << " -c1  = " << (-c1) << endl;
	//cout << " +c1  = " << (+c1) << endl;

	//cout << "conj(c1)" << conj(c1) << endl;
	//cout << "norm(c1)" << norm(c1) << endl;

	cout << "(c1 == c2) " << (c1 == c2) << endl;
	cout << "(c1 == 5) " << (c1 == 5) << endl;
	cout << "(6 == c1) " << (6 == c1) << endl;

	cout << "(c3 != c4) " << (c3 != c4) << endl;
	cout << "(c3 != 5) " << (c3 != 5) << endl;
	cout << "(6 != c3) " << (6 != c3) << endl;
	return 0;
}

注意点:

a. 文件开头引用头文件#include "complex.h"

a. 实现<<操作符,能将复数以自己的方式打印输出。



说明:本篇代码内容原文件放在下面百度云盘共享下http://pan.baidu.com/s/1kUNmj6B,使用编译器VS2013。


### 关于 `#include <bits/stdc++.h>` 的编译错误解决方案 `<bits/stdc++.h>` 是 GCC 特有的预定义头文件集合,包含了 C++ 标准库中的大部分常用功能。然而,在 Visual Studio 2022 中,默认情况下并不支持此头文件,这会导致编译失败[^1]。 #### 替代方法 为了使代码兼容 VS2022 并正常工作,建议采用以下几种替代方案之一: - **显式包含所需的标准库头文件** 如果项目依赖 `<bits/stdc++.h>` 来简化标准库函数和类的引入,则可以手动替换为具体所需的头文件声明。例如: ```cpp // 原始写法 (GCC/G++) #include <bits/stdc++.h> // 修改后的版本适用于 MSVC/VS2022 #include <iostream> #include <vector> #include <string> #include <algorithm> // 等等... ``` - **创建自定义 stdc++.h 文件** 可以为项目创建一个名为 `stdc++.h` 或其他名称的本地头文件,并在此文件内罗列所有必要的标准库导入语句。这样可以在不影响原有逻辑结构的前提下解决问题。 创建一个新的 `.h` 文件并添加如下内容: ```cpp /* 自定义 stdc++.h */ #ifndef STDCPP_H_ #define STDCPP_H_ // 插入实际需要使用的 STL 组件 #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <climits> #include <cassert> #include <functional> #include <utility> #include <map> #include <set> #include <stack> #include <queue> #include <deque> #include <list> #include <bitset> #include <sstream> #include <iomanip> #include <fstream> #include <complex> #include <valarray> #include <iterator> #include <memory> #include <typeinfo> #include <locale> #include <iosfwd> #include <streambuf> #include <cwchar> #include <cwctype> #include <codecvt> #include <exception> #include <stdexcept> #include <new> #include <limits> #include <random> #include <atomic> #include <thread> #include <mutex> #include <future> #include <condition_variable> #include <chrono> #include <ratio> #include <regex> #include <scoped_allocator> #include <tuple> #include <initializer_list> #include <type_traits> #include <cstdint> #include <cfenv> #include <cinttypes> #include <ctgmath> #endif // !STDCPP_H_ ``` 接着修改源码以引用新建立的头部文件: ```cpp #include "stdc++.h" ``` - **考虑跨平台开发工具链的选择** 对于那些希望保持代码一致性的开发者来说,可能还需要评估是否继续坚持使用特定于 GNU 工具链的功能特性。如果确实有必要保留这些特性,那么可以选择安装 MinGW-w64 或者 LLVM-MinGW 这样的第三方交叉编译环境来运行基于 GCC 的构建流程[^2]。 需要注意的是,某些特殊场景下(比如 WebRTC 开发),可能会涉及到更多复杂的配置调整以及额外依赖项处理等问题[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值