C++学习笔记一

编写目标、以良好的方式编写C++ 

1、构造函数是否为初始化函数

2、函数该不该加const (该加就要加)(函数里头不会改变data,就要加)

3、参数的传递尽量用pass by reference 还有要不要加const

4、数据几乎没有例外要放在private里

5、函数绝大部分放在public里

Object Based (基于对象)  (面对的是单一的class的设计)

classes的两种经典分类

1.class without pointer members       ------Complex

2.class with pointer members            ------String

 

Object Oriented(面向对象) (面对的是多重classes的设计,classes和classes之间的关系)

----继承 (inheritance)

----复合 (composition)

----委托  (delegation)

 

complex(复数)(不带指针)   (不带指针的函数多半不用析构函数)

1. 有实部和虚部  (决定内存占用大小)  (数据很多分)

2.加、减、乘、除、共轭、正弦...(函数处理实部虚部) (函数只有一份)

complex c1(2,1);
complex c2;
complex* pc = new complex(0,1);

string  (字符串)(带指针)

1.字符 s (其实是个ptr,指向一串字符)  (每一个数据里面只有一个指针)

2.拷贝,输出,附加,插入...

string s1("Hello ");
string s2("World ");
string* ps = new string;

C++ programs 代码的基本形式

Header(头文件)中的防卫式声明

complex.h

#ifndef __COMPLEX__
#define __COMPLEX__

...         //guard(防卫式声明)

#endif

complex-test.h

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

int main {}

Header (头文件)的布局

#ifndef __COMPLEX__
#define __COMPLEX__
//前置声明
#include <cmath>
class ostream;
class complex;

complex&
    __doapl (complex* ths, const complex& r);


//类的声明
class complex
{
...
};


//类的定义
complex::function ...
#endif

class  的声明 (declaration)  和  class template ( 模板)  简介

//T为类型
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 { return im; }
private:
T re, im;
friend complex& __doapl (complex*, const complex&);
};
{
complex<double> c1(2.5,1.5);
complex<int> c2(2,6);
...
}

inline   (内置函数)     

1.函数若在 class body內定义完成 , 便自动成为 inline 

2.函数若想在 class body外定义inline,只要头上加inline

inline double imag(const complex& x)
{
return x.imag ();
}

编译器决定是否真的inline(即使你想inline,要看编译器的能力)

 

access level()访问级别


1、private: 只能由该类中的函数、其友元函数访问,不能被任何其他访问,该类的对象也不能访问. 

2、public: 可以被该类中的函数、子类的函数、其友元函数访问,也可以由该类的对象访问.

3、protected: 可以被该类中的函数、子类的函数、以及其友元函数访问,但不能被该类的对象访问 .

 

初值列 、初始化列表(设初值)

constructor (ctor,  构造函数)        构造函数,无返回值类型

complex (double r = 0, double i = 0)   //默认实参(如果后期没有给初值的话,就用默认参数)
: re (r), im (i)  //initialization list  初值列 、初始化列表
{ }   //赋值 //分配内存 ,开一个窗口、文件都有可能

一般不建议用赋值的办法(跳过了初始化的一步,效率变低)

complex (double r = 0, double i = 0)
{ re = r; im = i; }   //assignments  赋值

ctor ( 构造函数)  可以有很多个 – overloading ( 重载)

1、同名函数可以重载(在编译器来看是不同名的)

2、函数重载常常发生在构造函数身上

3、如果构造函数已经拥有默认值,就不可以写如下会有冲突,但还是可以写其他的构造函数

complex () : re(0), im(0) { }   //不可以,不知道要调用那个构造函数,会有冲突
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 { return im; }
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};

void real(double r) const { re = r; }  //同名函数可以有多个
{
complex c1;
complex c2();
...
}

ctors  放在 private  里  (Singleton写法)

class A {
public:
    static A& getInstance();
    setup() { ... }
private:
    A();
    A(const A& rhs);  //重载
    ...
};
A& A::getInstance()
{
    static A a;
    return a;
}
A::getInstance().setup();

const member functions ( 常量成员函数)

如果在编程中确实有某个值保持不变,就应该明确使用const

double real () const { return re; }  //如果没有const,编译就可能会改变它的值就会出错
           //函数里头不会改变data,就要加      //这里没有改动re,只是把它取出来
const complex c1(2,1);

const修饰成员函数

(1)const修饰的成员函数不能修改任何的成员变量(mutable修饰的变量除外)

(2)const成员函数不能调用非onst成员函数,因为非const成员函数可以会修改成员变量

 

参数传递:pass by value (有多大传多大) VS  pass by reference (to const)  (传引用相当于传指针)

最好所有的参数传递都传引用(快又漂亮)

class complex
{
public:
complex (double r = 0, double i = 0)       //pass by value  (没有任何特殊符号)
: re (r), im (i)
{ }
complex& operator += (const complex&);         //pass by reference to const     (&取地址且const不该)
double real () const { return re; }
double imag () const { return 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)     //pass by referencez
{
return os << '(' << real (x) << ','
<< imag (x) << ')';
}

 

返回值传递 :return by value   VS return by reference(to const)

可以的情况下也尽量返回引用

class complex
{
public:
complex (double r = 0, double i = 0)
: re (r), im (i)
{ }
complex& operator += (const complex&);      //return by reference
double real () const { return re; }
double imag () const { return im; }
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};

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

friend (友元)

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 { return im; }
private:
double re, im;
friend complex& __doapl (complex*, const complex&);
};
inline complex&
__doapl (complex* ths, const complex& r)
{
ths->re += r.re;      
ths->im += r.im;
return *ths;
}

相同 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);
}

class body  外的各种定义(definitions)

do assignment plus

inline complex&
__doapl(complex* ths, const complex& r)
{
    ths->re += r.re;  //第一个参数不会被改变,第二个参数不会被改变
    ths->im += r.im;     //注意(+和=)与(+=)的区别
    return *ths;    //返回对象不会消亡,就用return by reference
}

inline complex&
complex::operator += (const complex& r)
{
    return __doapl (this, r);
}

二元操作符(操作符相当于函数,+= 

 操作符作用在左边身上,所以左边的参数就被隐藏的放进来,所以只要写右边就好了

operator overloading ( 操作符重载之1,  成员函数) this

所有的成员函数都一定带着一个隐含的参数(this不能写出来)

// += 的动作
//操作符设计,标准库就含有如下代码,我们只是把他调出来,方便其他类调用
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)   //但参数列不可能写出来this
           //操作符作用在左边身上,所以左边的参数就被隐藏的放进来,所以只要写右边就好了
           // 且右边又不需要动,所以引用参数要加const
{
    return __doapl (this, r);  //函数可以用this
         //返回得到左边这种东西(就是复数)
         //我们把这个函数要做的事情再推个上面的函数,所以传出去的值类型不会变
}

//你所传出去的东西,如果local object(这个函数本体创建的东西,那就可以传引用)
//右边加到左边身上,左边本来就存在,所以不是local object,就可以传引用
//而且这个函数创建在本体之外,所以可以加上inline,至于会不会真的成为inline,那是编译器自己的事

{
complex c1(2,1);
complex c2(5);
c2   +=    c1;    //将 c1 加到 c2 上 
}

inline complex&        //等价于上面第二个串代码
complex::operator += ( this, const complex& r)   //c2 就是(this)  +=    c1(r)
{               //操作符作用在左边身上,所以左边的参数就被隐藏的放进来,所以只要写右边就好了, 且右边又不需要动,所以引用参数要加const
     return __doapl (this, r);           //返回得到左边这种东西(就是复数)//我们把这个函数要做的事情再推个上面的函数,所以传出去的值类型不会变

你所传出去的东西,如果local object(这个函数本体创建的东西,那就可以传引用),右边加到左边身上,左边本来就存在,所以不是local object,就可以传引用,而且这个函数创建在本体之外,所以可以加上inline,至于会不会真的成为inline,那是编译器自己的事
}

return by reference 语法分析

传递者无需知道接收者是以什么(reference)形式接受

// += 的动作
inline complex&        //接受端       //返回声明返回的是reference  //返回类型
__doapl(complex* ths, const complex& r)   //左操作数是一根指针
{
    ...
    return *ths;     //传出指针所指的东西     //return by value
}

inline complex&
complex::operator += (const complex& r)         //pass by reference (to const)
{
    return __doapl(this,r);
}
{
complex c1(2,1);
complex c2(5);
c2   +=    c1;    //将 c1 加到 c2 上 
}
c3 += c2 += c1;   //如何是连串赋值,就不可以是value

class body  之外的各种定义 (definitions)

inline double imag(const complex& x)  //习惯用引用去传reference
{
return x.imag ();
}
inline double real(const complex& x)
{
return x.real ();
}
{
complex c1(2,1);
cout << imag(c1);
cout << real(c1);
}

operator overloading ( 操作符重载之2,  非成员函数) (无this)

+  左加右,既不能放再左身上,也不能放在右身上,必须创建一个新的东西给它(放在函数里头新创建的对象),所以它是一个local,就一定不能传引用,即return by  value

inline complex
operator + (const complex& x, const complex& y)       //全局函数
{
return complex (real (x) + real (y), imag (x) + imag (y));              //c2 = c1 + c2;
    //complex ()创建一个新的对象object,任何把创建的对象返回   ----临时对象
    //如果你把函数写在class里头就没法运用,复数加实数,实数加复数

}

inline complex
operator + (const complex& x, double y)
{
return complex (real (x) + y, imag (x));        //c2 = c1 + 5;
}

inline complex
operator + (double x, const complex& y)
{
return complex (x + real (y), imag (y));         //c2 = 7 + c1;
}
{
complex c1(2,1);
complex c2;
c2 = c1 + c2;
c2 = c1 + 5;
c2 = 7 + c1;
}

temp object (临时对象)      typename ();(相当于 int()  )  标准库一般用的多

下面这些函数绝不可以 return by reference ,因为, 它们返回的必定是个 local object.

complex ()创建一个新的对象object,任何把创建的对象返回   ----临时对象

//左边和右边相加,但是加的结果没处放,就需要创建出来,准备放结果
//前面是右边加到左边身上,所以右边已经存在啦
inline complex         //在complex中创建结果,离开complex函数就会死亡,外界没法用
operator + (const complex& x, const complex& y)
{
return complex (real (x) + real (y), imag (x) + imag (y));      //return by value
//complex ()创建一个新的对象object,任何把创建的对象返回   ----临时对象
}

inline complex
operator + (const complex& x, double y)   
{
return complex (real (x) + y, imag (x));       //return by value // typename ()
}

inline complex
operator + (double x, const complex& y)
{
return complex (x + real (y), imag (y));    //return by value // typename ()只不过有参数       
}
{
int(7);

complex c1(2,1);
complex c2;
complex();            //typename ()
complex(4,5);              //typename ()

cout << complex(2);        //typename ()
}

class body  之外的各种定义 (definitions)

inline complex         //可以pass by reference,没有产生新的结果
operator + (const complex& x)          //正号 ,一个参数就是正号
{
    return x;
}

//这个函数绝不可return by reference ,因为其返回的必定是个 local object
inline complex                                        
operator - (const complex& x)           //负号,一个参数
{
    return complex (-real (x), -imag (x));     //    typename(),一个临时对象
}
{
complex c1(2,1);
complex c2;
cout << -c1;      //创建复数之后可以取反(negate反向)
cout << +c1;
}

operator overloading ( 操作符重载,==相不相等), 非成员函数

inline bool
operator == (const complex& x,
const complex& y)
{
    return real (x) == real (y) && imag (x) == imag (y);
}

inline bool
operator == (const complex& x, double y)
{
    return real (x) == y && imag (x) == 0;
}

inline bool
operator == (double x, const complex& y)
{
    return x == real (y) && imag (y) == 0;
}
{
complex c1(2,1);
complex c2;

cout << (c1 == c2);
cout << (c1 == 2);
cout << (0 == c2);
}

operator overloading ( 操作符重载,!==不相等), 非成员函数

inline bool
operator != (const complex& x,const complex& y)
{
    return real (x) != real (y)|| imag (x) != imag (y);
}

inline bool
operator != (const complex& x, double y)
{
    return real (x) != y || imag (x) != 0;
}

inline bool
operator != (double x, const complex& y)
{
    return x != real (y) || imag (y) != 0;
}
{
complex c1(2,1);
complex c2;
cout << (c1 != c2);
cout << (c1 != 2);
cout << (0 != c2);
}

operator overloading ( 操作符(作用在左边身上)重载), 非成员函数

cout 就是ostream& os

//共轭复数(实部相等,虚部±相反)
inline complex    
conj (const complex& x)            //全局函数
{
    return complex (real (x), -imag (x));
}

//<<
#include <iostream.h>
ostream&   //不能加const ,有cout在改变
operator << (ostream& os, const complex& x)        //os一直在改变所以ostream& os不能加const
{
    return os << '(' << real (x) << ','<< imag (x) << ')';    //os一直在改变
}
{
    complex c1(2,1);
    cout << conj(c1);        //只能用全局写法
    cout << c1 << conj(c1);      //从左到右,因为可以连续传值,所以不设为void返回类型
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值