Class的两个分类
- class without pointer merber(s)
complex - class with pointer merber(s)
string
1 c/c++关于数据和函数
基于对象:面对的是单一的class的设计 面向对象:面对的是多重classes的设计,classes和classes之间的关系
2 c++程序代码基本形式
延伸文件名不一定是.h 和.cpp ,也可能是其他甚至没有。
2.1 主程序
#include <iostream>
#include "complex.h"
using namespace std;
int main()
{
return 0;
}
2.2 头文件中的防卫式声明
complex.h
#ifndef __COMPLEX__
#define __COMPLEX__
...
#endif
3 complex (without pointer)
3.1头文件布局
#ifndef __COMPLEX__
#define __COMPLEX__
#include<cmath>
class ostream;
class complex;
complex&
__doapl (complex* ths, const complex& r);
class complex
{
...
};
complex::function ...
#endif
3.2 class的声明
class complex
{
public:
complex (double r = 0, double i = 0)
: re (r), im(i)
{}
complex& operator += (const complex&);
double real () const {return re;}
double imag () const {reutn im;}
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};
{
complex c1(2,1);
complex c2;
...
}
3.3 类template(模板)简介
template<typename T>
class complex
{
public:
complex (T r = 0, T i = 0)
: re (r), im(i)
{}
complex& operator += (const complex&);
T real () const {return re;}
T imag () const {reutn im;}
private:
T re, im;
friend complex& __doapl (complex*, const complex&);
};
{
complex<double> c1(2.5,1.5);
complex<int> c2(2,6);
...
}
3.4 inline(内联)函数
如果函数在class body 内定义,自动成为inline候选 ,如果在class本体外定义就不是inline。 inline只是对编译器的建议,由编译器决定,如果函数太复杂,编译器就没有能力把函数变成inline。
inline double
imag(const complex& x)
{
return x.imag ();
}
3.5 访问级别
public :公开的外界能看得到 函数 private :只有class自己能看得到 数据 封装起来,不希望随便调用
{
complex c1(2,1);
cout << c1.re;
cout << c1.im;
}
{
complex c1(2,1);
cout << c1.real();
cout << c1.imag();
}
3.6 构造函数
如果想要创建一个对象 ,构造函数 会被自动调用。
- 构造函数一定要跟类的名字相同
- 它可以拥有参数
- 参数可以有默认值 //如果创建的时候没有指明参数,则使用默认值 其它函数也可以有默认值
- 没有返回类型 //
class complex
{
public:
complex (double r = 0, double i = 0)
: re (r), im(i)
{}
complex& operator += (const complex&);
double real () const {return re;}
double imag () const {reutn im;}
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};
一个变量数值的设定有两个阶段:初始化、赋值
complex (double r = 0, double i = 0)
{ re = r; im = i; }
构造函数对应析构函数 ,不带指针的类多半不用写析构函数
3.7 overloading(重载)
同名函数可以有很多个(实际不相同)——重载
- 函数重载常常发生在构造函数里
- 如果构造函数有默认值,不能重载为无默认值的函数
class complex
{
public:
complex (double r = 0, double i = 0)
: re (r), im(i)
{ }
complex () : re(0), im(0) { }
complex& operator += (const complex&);
double real () const {return re;}
double imag () const {reutn im;}
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};
void real(double r) { re = r; }
?real@Complex@@QBENXZ
?real@Complex@@QAENABN@Z
3.8 Singleton(单例)设计模式
把构造函数放在private,只允许外界创建一个例子
class A
{
public:
static A& getInstance();
setup() {...}
private:
A();
A(const A& rhs);
...
};
A& A::getInstance()
{
static A a;
return a;
}
A::getInstance().setup();
3.9 const成员函数
对class里面的函数分为会改变数据 和不会改变数据 两种,不会改变数据内容的加上const
class complex
{
public:
complex (double r = 0, double i = 0)
: re (r), im(i)
{ }
complex& operator += (const complex&);
double real () const {return re;}
double imag () const {reutn im;}
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};
{
complex c1(2,1);
cout << c1.real();
cout << c1.imag();
}
{
const complex c1(2,1);
cout << c1.real();
cout << c2.imag();
}
3.10 参数传递、返回值传递
3.10.1 参数传递:pass by value / pass by reference(to const)
- pass value:整个数据传过去,有多少传多少
- 引用底部就是一个指针,传引用相当于传指针那么快
- 最好所有参数传递都传引用
- 引用有指针的效果,当不希望改数据时加const
class complex
{
public:
complex (double r = 0, double i = 0)
: re (r), im(i)
{ }
complex& operator += (const complex&);
double real () const {return re;}
double imag () const {reutn im;}
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};
{
complex c1(2,1);
complex c2;
c2 += c1;
cout << c2;
}
ostream&
operator << (ostream& os, const complex& x)
{
return os << '(' << real (x) << ','
<< imag (x) << ')';
}
3.10.2 返回值传递:return by value / return by reference(to const)
complex& operator += (const complex&);
double real () const {return re;}
不能返回局部变量 的引用,除此之外都能return by reference,尽量传refernece 传递者 无需知道接收者 是以reference 形式接收 3.12.1
inline complex&
__doapl (complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
inline complex&
complex::operator += (const complex& r)
{
return __doapl (this, r);
}
3.11 friend(友元)
friend complex& __doapl (complex*, const complex&);
inline complex&
__doapl (complex* ths, const complex& r)
{
this->re += r.re;
this->im += r.im;
return *ths;
}
- 外部想要取数据通过public函数实现,友元friend可以直接拿private的数据。
- 友元效率更快,但是打破了封装。
相同class的各个objects 互为friends
class complex
{
public:
complex (double r = 0; double i = 0)
: re (r), im (i)
{ }
int func(const complex& param)
{ return param.re + param.im; }
private:
double re, im;
};
{
complex c1(2,1);
complex c2;
c2.func(c1);
}
3.12 操作符重载
3.12.1 操作符重载-1,成员函数(this)
传递者 无需知道接收者 是以reference 形式接收
inline complex&
__doapl(complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
inline complex&
complex::operator += (const complex& r)
{
return __doapl (this,r);
}
{
complex c1(2,1);
complex c2(5);
c2 += c1;
}
3.12.2 操作符重载-2,非成员函数(无this)
在class的body之外,带有class名称的是成员函数 ,不带class名称的是全域函数 。
{
complex c1(2,1);
cout << imag(c1);
cout << real(c1);
}
inline complex
operator + (const complex& x,const complex& y)
{
return complex(real (x) + real (y),
imag (x) + imag (y));
}
inline complex
operator + (const complex& x,double y)
{
return complex(real (x) + y, imag (x));
}
inline complex
operator + (double x,const complex& y)
{
return complex(x + real (y), imag (y));
}
这三个函数不带class名称,是全域函数。不能return by reference,因为他们返回的必定是local object 。
临时对象
typrname();
<< 操作符重载只能是全域函数,
ostream&
operator << (ostream& os, const complex& x)
{
return os << '('<< real (x) << ','<< imag (x) << ')';
}
{
cout << c1 << conj(c1);
}
3.13 class之外的各种定义
- 构造函数尽量用初值列
- 数据放在private
- 参数尽可能以reference传递,要不要加const
- 返回值尽量以reference传
- 类的body里的函数应该加const就要加
4 string (with pointer)
标准库类型String表示可变长的字符序列 字符直接量用单引号'' ,字符串直接两用双引号"" 字符串里面只有一个指针
定义和初始化String对象
string s1;
string s2(s1);
string s2 = s1;
string s3("value");
string s3 = "value";
string s4(n,'c');
如果使用等号初始化一个变量,执行的是拷贝初始化 ,编译器把等号右侧的初始值拷贝到新创建的对象中去。如果不适用等号,则执行的是直接初始化 。
|