1.c++編程簡介
所需基礎(chǔ)知識
. 某種編程語言: 變量、類型、作用域、循環(huán)、流程控制
. 編譯、連結(jié)建立可執(zhí)行程序
學(xué)習(xí)目標(biāo)
. 培養(yǎng)正規(guī)、大氣的變成習(xí)慣:以良好的方式編寫c++class及class之間的關(guān)系
c++歷史
. B (1969) -> C (1972) -> C++ (1983)
. newC -> C with class -> C++
. c++98 、c++03 、c++11、 c++14
. {c++語言,c++標(biāo)準(zhǔn)庫}
2.頭文件與類的聲明
c vs. c++?
. c:{數(shù)據(jù)和結(jié)構(gòu)數(shù)據(jù),函數(shù)},數(shù)據(jù)是全局的可以被各個函數(shù)處理
. c++:{類數(shù)據(jù)和類結(jié)構(gòu)數(shù)據(jù),類函數(shù)},數(shù)據(jù)與處理該數(shù)據(jù)的函數(shù)打包在一起創(chuàng)建出對象
c++,關(guān)于數(shù)據(jù)和函數(shù)
. complex:{實部和虛部,加減乘除共軛正弦等等}
. string:{字符(ptr指向字符串),復(fù)制輸出附加插入}
基于對象vs.面向?qū)ο?/p>
. Object Based :面對單一class的設(shè)計
. Object Oriented :面對多重classes的設(shè)計,classes與classes之間關(guān)系
Classes的兩個經(jīng)典分類
. Class without pointer member(s) : 不帶有指針的函數(shù),例complex
. Class with pointer member(s) : 帶有指針的函數(shù),例string
c++ programs 代碼基本形式
. .h頭文件:類生命
. .h頭文件:標(biāo)準(zhǔn)庫
. .cpp主程序:{ #include <標(biāo)準(zhǔn)庫文件> ?or ?#include "聲明文件" } , 擴展名可能為其他
c++vs.c : Output
. 使用iostream.h
?#include <iostream.h>?
using namespace std;
int main()
{
? ? int i = 7;
? ? cout << "i = " << i << endl;
? ? return 0;
}
Header頭文件中的防衛(wèi)式聲明
. 用于防止重復(fù)include
#ifndef __COMPLEX__
#define __COMPLEX__
{}
#endif
Header頭文件的布局
. 0:forward declarations 前置聲明
. 1:class declarations 類聲明
. 2:class definition 類定義
class聲明declaration
class complex ? ? ? ? ? ? //class head
{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//class body
? ? 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&);
}
. 有些函數(shù)在body中直接定義,另一些在body之外定義
class template 模板簡介
. 模板用于:當(dāng)類需要用于不同類型數(shù)據(jù)時
template<typename T>
class complex
{}
{
? ? complex<int>c1
? ? complex<double>c2
}
3.構(gòu)造函數(shù)
inline內(nèi)聯(lián)函數(shù)
. 函數(shù)在body中定義可形成inline函數(shù)
. inline functions 就像宏一樣,但沒有宏的缺點,速度較快較好
. 但如果函數(shù)太復(fù)雜則不能inline
. 由編譯器決定函數(shù)是否inline,用戶只可以建議inline
inline double
imag(const complex& x)
{
return x.imag () ;
}
access level 訪問級別
. 用關(guān)鍵字區(qū)分:public、private
. private 所以數(shù)據(jù)都應(yīng)該放入private;只被自己使用不想被外界使用的函數(shù)也放這里;
. public 放被外界使用的函數(shù)
. protected保護,例子暫無
. 錯誤方式:
{
? ? complex c1(2,1);
? ? cout << c1.re ; ? ? ? ? ?// re變量只在private部分定義,不可以拿出來直接用
? ? cout << c1.im; ? ? ? ? ?//im同上
}
. 正確方式:
{
? ? complex c1(2,1);
? ? cout << c1.real(); ? ? ? ? //real函數(shù)定義于public部分,可以使用
? ? cout << c1.imag(); ? ? ?//imag同上
}
constructor. (ctor,構(gòu)造函數(shù))
. 函數(shù)名稱要與類名稱相同
. 參數(shù)與類中定義一致
. 參數(shù)默認(rèn)值default argument,創(chuàng)建時沒有指明參數(shù)值時使用默認(rèn)值
. 構(gòu)造函數(shù)沒有返回類型
? ? public:
? ? ? ? complex (double r = 0, double i = 0) ? ? ? ?//default argument
? ? ? ? ? : re (r) , im (i)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //initialization list? 初始值,初始列,給變量設(shè)置初始值,好的寫法,不將初始化寫入函數(shù)中,區(qū)分于函數(shù)中的賦值動作,充分應(yīng)用專門功能
? ? ? ? {} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
. 使用構(gòu)造函數(shù)
{
? ? complex c1(2,1);
? ? complex c2;
? ? complex* p = new complex(4); ? ? ? ? ?//動態(tài)創(chuàng)建,得到的是指針
}
. ctor構(gòu)造函數(shù)可以有很多個 - overloading 重載(即相同函數(shù)有很多個,如多種初值設(shè)定)
. 當(dāng)有多個構(gòu)造函數(shù)時,編譯器會在編譯后的實際名稱中加以區(qū)分
. 已經(jīng)存在有默認(rèn)值的構(gòu)造函數(shù),則不能再有無參數(shù)的相同構(gòu)造函數(shù)
4.參數(shù)傳遞與返回值
constructor(ctor)構(gòu)造函數(shù)放在private區(qū)
. 當(dāng)不允許外界創(chuàng)建類時,例如設(shè)計模式中的Singleton,只允許一個存在,外界通過函數(shù)取得
const member functions 常量成員函數(shù)
. 函數(shù)后加const,小括號后花括號前;對象前也可加const
. 不改變數(shù)據(jù)內(nèi)容的函數(shù),一定要加const
. 函數(shù)不加const的話,而當(dāng)用戶在對象前加const,編譯時候會出現(xiàn)矛盾
double real () const {return re;}
參數(shù)傳遞 pass by value vs. pass by reference (to const)
. by value:直接傳遞數(shù)值,整包value都傳過去,壓入函數(shù)棧。盡量不要用!
. by reference:傳遞引用地址,相當(dāng)于傳遞指針的速度
. 傳遞引用不希望數(shù)據(jù)被修改時,前加const
ostream&
operator << (ostream& os, const complex& x)
{
return os << '(' << real (x) << ','
? ? ? ? ? ? ? ?<< imag (x) << ')' ? ?;
}
. 參數(shù)返回時也盡量要by reference
friend (友元)
. friend函數(shù)可以取得private數(shù)據(jù)
inline complex& __doapl (complex* ths, const complex& r)
{
? ? ths ->rm += r.re;
? ? ths ->im +=r.im;
? ? return *ths;
}
. friend會打破封裝,選擇時需要考慮
. 相同class的各個objects互為friends友元
class complex
{
? ? public:
? ? ? ? complex ()
? ? ? ? : 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
. 什么情況可以pass by reference
. 什么情況可以return by reference:local變量要pass by value,其余都可以
5.操作符重載與臨時對象
. 在c++中操作符即是函數(shù),可以被重新定義
operator overloading操作符重載-1,this(成員函數(shù))
. 在成員函數(shù)中調(diào)用操作符的變量為this,但在參數(shù)列中不寫,調(diào)用時候可以寫
inline complex&
complex::operator += (const complex& r)
{
? ? return __doapl (this,r);
}
{
complex c1(2,1);
complex c2(5);
c2 += c1;
}
. doapl:賦值相加
return by reference 語法分析
. 傳送者無需知道接受者是否以reference形式接收,by value使用方法也一樣
inline complex&?
__doapl(complex* ths,const complex& r)
{
...
return *ths;
}
inline complex&?
complex::operator += (const complex& r)
{
return __doapl(this,r);
}
. 當(dāng)有連串動作發(fā)生時,如c3+=c2+=c1;返回值不可以是void
class body 之外的各種定義definition
operator overloading操作符重載2無this(非成員函數(shù))
. 為了應(yīng)付client的三種可能用法,需要對應(yīng)開發(fā)三個函數(shù)(復(fù)+復(fù),復(fù)+實,實+復(fù))
. 全局函數(shù),沒有this,調(diào)用參數(shù)要寫全,函數(shù)名前沒有class名
temp object 臨時對象 typename();
. 下面函數(shù)絕不可return by reference,因為他們返回值必須是個local object
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) ) ;
}
. 創(chuàng)建臨時對象:typename();不需要命名。括號中可有參數(shù),生命到下一行就結(jié)束了
. 正負(fù)操作符,正操作符可試一下return by reference看看是否可行,負(fù)操作符必須return by value
. 相等、不等操作符,基本同前
. 共軛
. 對于output operator 等特殊操作符,不可以寫為成員函數(shù),只能將其重載為global函數(shù)
. 輸入流ostream&前不可加const .也有連串使用情況,所以要考慮返回值
inline complex
conj (const complex& x)
{
return complex (real (x), -imag (x));
}
#include <iostream.h>
ostream&
operatro << (ostream& os, const complex& x)
{
return os << '(' <<real (x) << ',' << imag (x) << ')' ;
}
{
? ? complex c1(2,1);
? ? cout << conj(c1);
? ? cout << c1 << conj(c1);
}
總結(jié)整理:
.注意點:防衛(wèi)式定義一定要有、初始行要用、函數(shù)一定要考慮加不加const、參數(shù)盡量pass by reference以及是否加const、考慮return by reference、數(shù)據(jù)幾乎無外放在private、函數(shù)大多放在public?