欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c++ 成員函數(shù)與非成員函數(shù)的抉擇

 更新時(shí)間:2013年01月02日 16:34:22   投稿:mdxy-dxy  
盡量用類的非成員函數(shù)以及友元函數(shù)替換類的成員函數(shù) 例如一個(gè)類來模擬人People

1.盡量用類的非成員函數(shù)以及友元函數(shù)替換類的成員函數(shù) 例如一個(gè)類來模擬人People

復(fù)制代碼 代碼如下:

1 class People{
2 public:
3 ...
4 void Getup( );
5 void Washing( );
6 void eating( );
7 ...
8 }

其實(shí)上面三個(gè)動(dòng)作是早上“起床”、“洗簌”、“吃飯”三個(gè)常見的動(dòng)作,如果現(xiàn)在用一個(gè)函數(shù)來表示使用成員函數(shù)即為
復(fù)制代碼 代碼如下:

1 class People
2 {
3 ...
4 void morningAction( )
5 {
6 Getup( );
7 Washing( );
8 eating( );
9 }
10 }

如果寫一個(gè)非成員函數(shù)即為
復(fù)制代碼 代碼如下:

1 void moringAction(People& p)
2 {
3 p.Getup( );
4 p.Washing( );
5 p.eating( );
6 }

那么是選擇類的成員函數(shù)還是類的非成員函數(shù)呢?

面向?qū)ο髣t要求是,將操作數(shù)據(jù)的函數(shù)與數(shù)據(jù)放在一起。但這不意味著要選擇成員函數(shù)。從封裝的角度看,成員函數(shù)的moringAction封裝性比非成員函數(shù)要低。如果某些東西被封裝,它就不再可見。越多東西被封裝,越少人可以看到它。所以使用非成員函數(shù)的類,封裝性較低。而越少人看到它,我們就有越大彈性去變化它,因?yàn)槲覀兊母淖儍H僅直接影響看到改變的那些人事物。因此,越多東西被封裝,改變哪些東西能力越大。

在考慮對(duì)象內(nèi)的數(shù)據(jù)。越少的代碼可以看到數(shù)據(jù)(訪問它),越多的數(shù)據(jù)可以被封裝,而我們也就越能自由改變對(duì)象數(shù)據(jù)。現(xiàn)在如果一個(gè)成員函數(shù)、非成員函數(shù)都能提供相同的機(jī)能,我們選擇非成員函數(shù)。

在說下面內(nèi)容之前我們先談?wù)凜++中的類型轉(zhuǎn)換分顯示類型轉(zhuǎn)換和隱式類型轉(zhuǎn)換。

2.顯示類型轉(zhuǎn)換

C++有顯示類型轉(zhuǎn)換操作符分別為:static_cast,const_cast,dynamic_cast和reinterpret_cast


2.1static_cast
轉(zhuǎn)換功能與C風(fēng)格類型轉(zhuǎn)換一樣,含義也一樣。通過使用static_cast可以使沒有繼承關(guān)系的類型進(jìn)行轉(zhuǎn)換。但是要注意不能將內(nèi)置類型轉(zhuǎn)化為自定義類型,或者將自定義類型轉(zhuǎn)化為內(nèi)置類型,并且不能將cosnt類型去掉,但能將non-cosnt類型轉(zhuǎn)換為const類型。例如:
char a='a';

int b=static_cast<int>(a);
兩個(gè)類型之間的轉(zhuǎn)換,其實(shí)也是要自己實(shí)現(xiàn)支持,原理和內(nèi)置類型之間轉(zhuǎn)換相似。
復(fù)制代碼 代碼如下:

1 #include <iostream>
2 class Car;
3
4 class People
5 {
6 public:
7 People(int a,int h)
8 :age(a),height(h)
9 {}
10
11 inline int getAge() const
12 {
13 return age;
14 }
15
16 inline int getHeight() const
17 {
18 return height;
19 }
20
21 People & operator=(const Car& c);
22 private:
23 int age;
24 int height;
25 };
26
27 class Car
28 {
29 public:
30 Car(double c, double w)
31 :cost(c),weight(w)
32 {}
33
34 inline double getCost() const
35 {
36 return cost;
37 }
38
39 inline double getWeight() const
40 {
41 return weight;
42 }
43
44 Car & operator=(const People& c);
45 private:
46 double cost;
47 double weight;
48 };
49
50 People & People::operator=(const Car& c)
51 {
52 age = static_cast<int>(c.getCost());
53 height = static_cast<int>(c.getWeight());
54 return *this;
55 }
56
57 Car & Car::operator=(const People& c)
58 {
59 cost = static_cast<double>(c.getAge());
60 weight = static_cast<double>(c.getHeight());
61 return *this;
62 }
63
64 int main(int argc,char * argv[])
65 {
66 Car c(1000.87,287.65);
67 People p(20,66);
68 People p2(0,0);
69 Car c2(0.00,0.00);
70 p2=c;
71 c2=p;
72 std::cout<< "car'info: cost is " << c2.getCost() << ". weight is " << c2.getWeight() <<std::endl;
73 std::cout<< "people'info: age is " << p2.getAge() <<". height is " << p2.getHeight() <<std::endl;
74 return 0;
75 }

運(yùn)行結(jié)果為
car'info: cost is 20. weight is 66
people'info: age is 1000. height is 287

2.2const_cast
主要用來去掉const和volatileness屬性,大多數(shù)情況下是用來去掉const限制。


2.3dynamic_cast
它用于安全地沿著繼承關(guān)系向下進(jìn)行類型轉(zhuǎn)換。一般使用dynamic_cast把指向基類指針或者引用轉(zhuǎn)換成其派生類的指針或者引用,并且當(dāng)轉(zhuǎn)換失敗時(shí)候,會(huì)返回空指針。


2.4reinterprit_cast
該轉(zhuǎn)換最普通用途就是在函數(shù)指針類型之間進(jìn)行轉(zhuǎn)換。
復(fù)制代碼 代碼如下:

1 typedef void (*fun) ( ) //一個(gè)指向空函數(shù)的指針
2 fun funArray[10]; //含有10個(gè)函數(shù)指針的數(shù)據(jù)。
3 int function( ); //一個(gè)返回值為int類型函數(shù)
4 funArray[0] = &function( ) //錯(cuò)誤!類型不匹配
5 funArray[0] = reinterpret_cast<fun>(&function); //ok注意轉(zhuǎn)換函數(shù)指針的代碼是不可移植的。

一般應(yīng)該避免去轉(zhuǎn)換函數(shù)指針類型。

3.使用非成員函數(shù)可以發(fā)生隱式轉(zhuǎn)換
C++是支持隱式類型轉(zhuǎn)換的,例如在做運(yùn)算的時(shí)候,或者傳遞參數(shù)給函數(shù)的時(shí)候常常會(huì)發(fā)生隱式類型轉(zhuǎn)換。
假設(shè)你設(shè)計(jì)一個(gè)class用來表現(xiàn)有理數(shù)。其實(shí)令類支持隱式類型轉(zhuǎn)換是一個(gè)槽糕的決定。當(dāng)然在建立數(shù)值類型時(shí)就是例外。下面定義一個(gè)有理數(shù)類型:
復(fù)制代碼 代碼如下:

1 class Rational {
2 public:
3 Rational( int numerator = 0,int denominator =1 );
4 int numerator( ) const;
5 int denominator ( ) const ;
6 private:
7 ...
8 }

有理數(shù)類型想當(dāng)然支持算數(shù)運(yùn)算,但是不確定是否聲明為成員函數(shù)或非成員函數(shù)或者是友元函數(shù)來實(shí)現(xiàn)它們。

首先是考慮成員函數(shù)寫法:
復(fù)制代碼 代碼如下:

1 class Rational {
2 public:
3 ...
4 const Rational operator* (const Rational& rhs) const;
5 ...
6 }
7 Rational testOne(1,4);
8 Rational testTwo(1,1);
9 //做算術(shù)運(yùn)算
10 Rational result = testOne * testTwo;
11 //與常量做運(yùn)算
14 result = 2 * testOne //error!!

那么為什么將常量提前就錯(cuò)誤了呢?這里我們換一種寫法
復(fù)制代碼 代碼如下:

1 result = testOne.operator*(2); //ok
2 result =2.operator*(oneHalf); //error

這里發(fā)生了什么?其實(shí)在第一行式子里發(fā)生了所謂隱式類型轉(zhuǎn)換。哪里發(fā)生了隱式類型轉(zhuǎn)換呢?看上面的代碼operator*函數(shù)參數(shù)是const Rational類型,而2是一個(gè)cosnt int類型,。編譯器發(fā)現(xiàn)有non-explicit型的單參數(shù)類為int類型的構(gòu)造函數(shù),可以造出Rational類型。所以編譯器那樣做了,發(fā)生了隱式類型轉(zhuǎn)換。所以第一個(gè)式子可以正常運(yùn)行,但是第二個(gè)是沒有將Rational類型轉(zhuǎn)換為int類型的。
設(shè)計(jì)出上面兩個(gè)式子正常運(yùn)行才算合理的運(yùn)行。
復(fù)制代碼 代碼如下:

1 class Rational{
2 ...
3 };
4 const Rational operator*(const Rational & lhs, const Rational & rhs)
5 {
6 return Rational(lhs.numerator() * rhs.numerator(),lhs.denominator() * rhs.denominator() );
7 }
8 Rational testOne(1, 4);
9 Rational result;
10 result = oneFourth *2;
11 result = 2 * oneFourth; 通過
12 }

按上面代碼設(shè)計(jì)成非成員函數(shù),那么在調(diào)用int類型整數(shù)的時(shí)候會(huì)發(fā)生隱式類型轉(zhuǎn)換。
operaotr* 是否應(yīng)該稱為Rational class的一個(gè)友元函數(shù)呢?對(duì)本例子而言,完全沒有必要。

如果你需要為某個(gè)函數(shù)所有參數(shù)進(jìn)行類型轉(zhuǎn)換,那么這個(gè)函數(shù)必須是個(gè)非成員函數(shù)。

4.謹(jǐn)慎使用隱式類型轉(zhuǎn)換
我們對(duì)一些類型隱式轉(zhuǎn)換無能為力,因?yàn)樗鼈兪钦Z言本身的特性。不過當(dāng)編寫自定義類時(shí),我們可以選擇是否提供函數(shù)讓編譯器進(jìn)行隱式類型轉(zhuǎn)換。
有兩種函數(shù)允許編譯器進(jìn)行隱式類型轉(zhuǎn)換:單參數(shù)構(gòu)造函數(shù)與隱式類型轉(zhuǎn)換運(yùn)算符。
復(fù)制代碼 代碼如下:

1 public Name{
2 public:
3 Name(const string& s); //轉(zhuǎn)換string到Name
4
5 ...
6 };
7
8 class Rational { //有理數(shù)類
9 public:
10 //轉(zhuǎn)換從int到有理數(shù)類
11 Rational(int numerator=0,int denominatior =1);
12 ...
13 }

C++是支持隱式類型轉(zhuǎn)換的,例如在做運(yùn)算的時(shí)候,或者傳遞參數(shù)給函數(shù)的時(shí)候常常會(huì)發(fā)生隱式類型轉(zhuǎn)換。有兩種函數(shù)允許編譯器進(jìn)行隱式轉(zhuǎn)換。單參數(shù)構(gòu)造函數(shù)和隱式類型轉(zhuǎn)換運(yùn)算符。

也許前面說道了一些隱式類型轉(zhuǎn)換帶來的方便之處,下面說說一些麻煩之處。
復(fù)制代碼 代碼如下:

1 template<class T>
2 class Array{
3 Array(int lowBound,int highBound);
4 Array(int size);
5 T& operator[](int index);
6 ...
7 };
8 bool oerpator==(const Array<int>& lhs,const Array<int>& rhs);
9 Array<int> a(10);
10 Array<int> b(10);
11 ...
12 for(int i=0;i < 10; ++i)
13 if(a == b[i]) {
14 ... }
15 else
16 {
17 ...
18 }

如果這里不小心將數(shù)組a的下標(biāo)忘記寫了,這里編譯器應(yīng)該報(bào)出警告信息,但是其實(shí)是沒有的。因?yàn)榫幾g器將a看成Array<int>類型,b為 int,根據(jù)上面的經(jīng)驗(yàn),編譯器看到一個(gè)non-explicit單參數(shù)構(gòu)造函數(shù)其參數(shù)類型為int,而且operator需要一個(gè)Array<int>類型,那么編譯器就這樣做了,發(fā)生了隱式類型轉(zhuǎn)換。相信如果真的發(fā)生這樣,會(huì)很麻煩。
怎么樣避免呢?將構(gòu)造函數(shù)聲明為explicit。避免隱式類型轉(zhuǎn)換。

相關(guān)文章

  • C語言直接插入排序算法介紹

    C語言直接插入排序算法介紹

    大家好,本篇文章主要講的是C語言直接插入排序算法介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 詳解C語言編程中的函數(shù)指針以及函數(shù)回調(diào)

    詳解C語言編程中的函數(shù)指針以及函數(shù)回調(diào)

    這篇文章主要介紹了C語言編程中的函數(shù)指針以及函數(shù)回調(diào),函數(shù)回調(diào)實(shí)際上就是讓函數(shù)指針作函數(shù)參數(shù)、調(diào)用時(shí)傳入函數(shù)地址,需要的朋友可以參考下
    2016-04-04
  • va_list(),va_start(),va_arg(),va_end() 詳細(xì)解析

    va_list(),va_start(),va_arg(),va_end() 詳細(xì)解析

    這些宏定義在stdarg.h中,所以用到可變參數(shù)的程序應(yīng)該包含這個(gè)頭文件.下面我們寫一個(gè)簡單的可變參數(shù)的函數(shù),該函數(shù)至少有一個(gè)整數(shù)參數(shù),第二個(gè)參數(shù)也是整數(shù),是可選的.函數(shù)只是打印這兩個(gè)參數(shù)的值
    2013-09-09
  • C語言詳細(xì)講解樹狀數(shù)組與線段樹

    C語言詳細(xì)講解樹狀數(shù)組與線段樹

    顧名思義,樹狀數(shù)組就是用數(shù)組來模擬樹形結(jié)構(gòu)唄。那么衍生出一個(gè)問題,為什么不直接建樹,因?yàn)闃錉顢?shù)組能處理的問題就沒必要建樹。線段樹是一種二叉搜索樹,與區(qū)間樹相似,它將一個(gè)區(qū)間劃分成一些單元區(qū)間,每個(gè)單元區(qū)間對(duì)應(yīng)線段樹中的一個(gè)葉結(jié)點(diǎn)
    2022-04-04
  • C++如何實(shí)現(xiàn)簡單的計(jì)時(shí)器詳解

    C++如何實(shí)現(xiàn)簡單的計(jì)時(shí)器詳解

    因?yàn)樽罱e著無聊就想著要不用C++寫點(diǎn)什么東西,仔細(xì)想了想其實(shí)自己的C++學(xué)的也不怎么好,寫個(gè)簡單的計(jì)時(shí)器吧!所以下面這篇文章主要介紹了利用C++如何實(shí)現(xiàn)簡單的計(jì)時(shí)器,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • C語言實(shí)現(xiàn)學(xué)生學(xué)籍管理系統(tǒng)課程設(shè)計(jì)

    C語言實(shí)現(xiàn)學(xué)生學(xué)籍管理系統(tǒng)課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)學(xué)生學(xué)籍管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • C++深入探究友元使用

    C++深入探究友元使用

    采用類的機(jī)制后實(shí)現(xiàn)了數(shù)據(jù)的隱藏與封裝,類的數(shù)據(jù)成員一般定義為私有成員,成員函數(shù)一般定義為公有的,依此提供類與外界間的通信接口。但是,有時(shí)需要定義一些函數(shù),這些函數(shù)不是類的一部分,但又需要頻繁地訪問類的數(shù)據(jù)成員,這時(shí)可以將這些函數(shù)定義為該類的友元函數(shù)
    2022-07-07
  • 詳解VS2019 dumpbin查看DLL的導(dǎo)出函數(shù)

    詳解VS2019 dumpbin查看DLL的導(dǎo)出函數(shù)

    這篇文章主要介紹了詳解VS2019 dumpbin查看DLL的導(dǎo)出函數(shù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • opencv實(shí)現(xiàn)視場(chǎng)轉(zhuǎn)換

    opencv實(shí)現(xiàn)視場(chǎng)轉(zhuǎn)換

    這篇文章主要為大家詳細(xì)介紹了opencv實(shí)現(xiàn)視場(chǎng)轉(zhuǎn)換,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • C++中拷貝構(gòu)造函數(shù)的使用

    C++中拷貝構(gòu)造函數(shù)的使用

    大家好,本篇文章主要講的是C++中拷貝構(gòu)造函數(shù)的使用,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02

最新評(píng)論