Talk is cheap. Show me the code.
C++分为C++语言和C++标准库
版本演化可分为C++98(1.0) , C++11(2.0) , C++14
话不多说,上代码
头文件命名方式,例如complex.h
首先要写防卫式声明,以前写的时候只是知道要写,现在知道才叫什么。
1 #ifndef _MYCOMPLEX_ 2 #define _MYCOMPLEX_ 3 4 . . . 5 6 #endif
然后写你要声明的类
类声明
1 class complex 2 { 3 public: 4 complex (double r = 0, double i = 0)//尝试改成传引用,得是大的,类似string 5 : re (r), im (i) 6 { }//在里面开文件,申请内存什么的 7 8 complex& operator += (const complex&);//成员函数 9 10 double real () const { return re; }//注意const 11 double imag () const { return im; } 12 private: 13 double re, im; 14 15 friend complex& __doapl (complex *, const complex&); 16 17 };
complex是名称,然后写成员变量re im,注意设置私有访问级别,12 13行。
考虑函数是成员函数还是非成员函数
写成员函数,设置访问级别为公用访问级别,构造函数为4 5 6行,第四行可以传引用,例如在传字符串的时候使用,在一些情况下必须使用初始化列表,例如需要初始化const修饰的类成员,花括号里面以后可以放一些其他操作,例如打开文件
8 9 10行是成员函数,8行是操作符重载,使用了this指针,其中用const指明传入值不可改变,9 10行的const要注意不可改变返回值,注意返回值尽量设置为reference,意思是先考虑返回renference,实在不行再用value.
15行是友元friend,表示此函数可以自由取得private成员
1 inline complex& 2 complex::operator += (const complex& r) 3 { 4 return __doapl (this, r); 5 }
这里this指针回自行调用,写函数时先写名称,注意格式,再写参数,reference还是value,返回值是什么形式,最后是内部操作
1 inline complex& 2 __doapl (complex* ths, const complex& r) 3 { 4 ths->re += r.re; 5 ths->im += r.im; 6 return *ths; 7 }
inline表示内联,是对编译器的一种建议,至于编译器接受不接受不一定,内联函数不要太大,没有循环体。
注意return的是指针,接收的是reference,此为传入者无需知道接收者是以reference形式接收
写C++文件,命名complex.cpp
1 #include <iostream> 2 #include "complex.h" 3 4 using namespace std; 5 6 ostream& 7 operator << (ostream& os, const complex& x) 8 { 9 return os << '(' << x.real () << ',' << x.imag () << ')'; 10 } 11 12 int main() 13 { 14 complex c1(2, 1); 15 complex c2(4, 0); 16 cout << (c1 += c2) << endl; 17 return 0; 18 }
1 2行是对头文件进行包含,4行是对命名空间的包含,此为标准库,6 7 8 9 10行是对操作符号的重载,cout属于ostream类,必须要有返回值,因为涉及连续传输操作
执行结果为
1 (6,1)
上面所说的是Complex class,下面讲述 String class,区别在于后者有指针,需要三大函数(Big Three)
先写头文件string.h,写入防卫式声明
然后写类,命名String
1 class String 2 { 3 public: 4 String(const char* cstr=0); 5 String(const String& str); 6 String& operator=(const String& str); 7 ~String(); 8 char* get_c_str() const { return m_data; } 9 private: 10 char* m_data; 11 };
考虑成员变量,设置private,字符串用指针比用数组更合适,涉及动态分配内存
考虑成员函数,设置public,4行为构造函数,5行为拷贝构造函数,6行为拷贝复制,7行为析构函数,5 6 7行函数被称为三大函数
构造函数负责申请空间,存储字符串,而析构函数负责删除字符串,回收空间
1 inline 2 String::String(const char* cstr) 3 { 4 if (cstr) { 5 m_data = new char[strlen(cstr)+1]; 6 strcpy(m_data, cstr); 7 } 8 else { 9 m_data = new char[1]; 10 *m_data = '\0'; 11 } 12 } 13 14 inline 15 String::~String() 16 { 17 delete[] m_data; 18 }
拷贝构造:没有存在一个字符串,需要创建一个再把一个字符串复制过来
1 inline 2 String::String(const String& str) 3 { 4 m_data = new char[ strlen(str.m_data) + 1 ]; 5 strcpy(m_data, str.m_data); 6 }
输入值为字符串的reference,无返回值,4行使用new申请内存空间,5行调用strcpy函数复制,属于深拷贝
使用strcpy,必须包含它的头文件
1 #include <cstring>
拷贝构造使用方法
1 String s3(s2);
拷贝复制:存在两个字符串,把其中一个字符串复制到另一个字符串里
1 inline 2 String& String::operator=(const String& str) 3 { 4 if (this == &str) 5 return *this; 6 7 delete[] m_data; 8 m_data = new char[ strlen(str.m_data) + 1 ]; 9 strcpy(m_data, str.m_data); 10 return *this; 11 }
属于操作符重载,输入值为右值字符串的reference,输出值为字符串的reference,4 5行为检测自我赋值(处理或排除一些特殊情况,例如自我赋值,为空,超出范围等等)
采用this指针代表左值,7行,删除左值,也就是清除左值内容,释放左值内存,8 9行为拷贝构造内容,返回this指针
假设不写’检测自我赋值‘这两行代码,那么你将要复制的右值和你想要赋值的左值为同一空间,在执行删除左值时,将直接删除你的右值,程序虽不会报错,但会输出错误(不信你就试试)
1 s3 = s1;
写的string_test.cpp如下
1 #include "string.h" 2 #include <iostream> 3 4 using namespace std; 5 6 ostream& operator<<(ostream& os, const String& str) 7 { 8 os << str.get_c_str(); 9 return os; 10 } 11 12 int main() 13 { 14 String s1("hello"); 15 String s2("world"); 16 17 String s3(s2); 18 cout << s3 << endl; 19 s3 = s1; 20 s1 = s1; 21 cout << s3 << s2 << endl; 22 cout << s2 << endl; 23 cout << s1 << endl; 24 }
输出结果如下
1 world 2 helloworld 3 world 4 hello
标签:const,String,基础,C++,complex,str,data,函数 From: https://www.cnblogs.com/linchangchao/p/17603722.html