1、友元函數
在類中一般的成員函數具備:
(1)、該函數能通路類中的私有部分
(2)、該函數位于類的作用域之中
(3)、該函數必須經由一個對象去激活,也就是說有一個this指針;
友元函數不同之處:
(1)、在#include<iostream> using namespace std;的前提下,必須的類外先聲明;
class Test;
void fun(); //有元函數的聲明
但是在#include<iostream.h>中不用這個有元函數的聲明;這是早期頭檔案的包含。
(2)、在類内必須聲明是朋友,friend(關鍵字),函數聲明
class Test{
friend void fun(); //朋友沒有公有,私有,保護之分,是以限定修飾符在這不起任何作用
};
(3)、在類外實作方法的定義,此時不用再加friend了;
void fun(){
..........
}
有元函數具有的特性:該函數能通路類的私有資料;不是該類的成員函數,也不需要對象驅動;

還有友元類,跟其使用一樣,類中所有函數均可調用其朋友的私有資料;
2、運算符的重載(個人認為C++中運算符的重載很有用,也很重要)
相當于函數的調用,對其的另一種更加人文化的解釋,并告訴 C++編譯器,遇到該重載運算符時調用此函數。
定義運算符重載的一般格式:
傳回值類型 類名::operator重載的運算符(參數清單);
假如出現複數類:
Complex{
public:
.....
private:
int real;
int p_w_picpath;
};
//主函數中:
Complex t1(1, 2);
Complex t2(2, 3);
Complex t3;
t3 = t1 + t2;
此時t1和t2的類型不定,就得對+進行運算符的重載;使其更符合人文化,其本質不變,t1.operator+(t2);
對象的類型不定,編譯器不知道怎麼輸出,自己就得對<<和>>運算符進行重載,以達到輸出對象的目的。還必須是友元函數;
class Complex; //這是第一步,類外聲明。
ostream& operator<<(ostream &out, const Complex &c);
istream& operator>>(istream &in, Complex &c);
class Complex{ //這是第二步,對其在類内說明是朋友。
friend ostream& operator<<(ostream &out, const Complex &c);
friend istream& operator>>(istream &in, Complex &c);
};
ostream& operator<<(ostream &out, const Complex &c){
out<<"("<<c.m_real<<","<<c.m_imag<<")";
return out; //這是第三步,在類外進行定義。
}
istream& operator>>(istream &in, Complex &c){
in>>c.m_real>>c.m_imag;
return in;
}
關于這個<<對應一個要輸出的值,在定義時,不用endl,回車。
對于Complate類的補充,t1 = t2 + 10; //成員方法重載即可。内部有一個隐藏參數
t1 = 10 + t2; //沒有對象驅動,還要10.operator+(t2);是錯的,是以此時用友元函數,傳兩個參數就是有兩個參數。
運算符的重載要注意:
(1)、operator後面是一個合法的運算符,将右操作數做為函數的實參;
(2)、++ --前後的問題,用函數重載區分,後加的(int)參數;
(3)、?: . .* :: sizeof不能重載,其它的應該都可以進行重載;
例1:++i 和 i++有什麼差別?
對其進行重載,如下:
#include<iostream>
using namespace std;
class Int;
ostream& operator<<(ostream &out, const Int &s);
class Int{
friend ostream& operator<<(ostream &out, const Int &s);
public:
Int(int m = 0) : t(m){}
~Int(){}
public:
Int& operator++()//++t 先加1,再将此對象的引用傳回
{
t++;
return *this;
}
Int operator++(int) //t++ 後加的要有一個參數int區分,
{
Int tmp(t); //建立一個臨時對象,
t++; //原有對象加了一下,
return tmp; //傳回臨時對象,後加。
}
private:
int t;
};
ostream& operator<<(ostream &out, const Int &s){
out<<s.t;
return out;
}
int main(void){
Int t1(6);
Int t2;
Int t3;
t2 = ++t1;
cout<<"t1 = "<<t1<<", t2 = "<<t2<<endl; //對輸出運算符重載了,才能輸出對象。
t3 = t1++;
cout<<"t1 = "<<t1<<", t3 = "<<t3<<endl;
return 0;
}
運作結果如下:
從結果可以看出,确是實作了,這塊的本質是運算符對++的重載。
前加,傳回的是引用,後加還得調用構造函數和拷貝構造;是以前加++i;效率更高,運作速度也更快。
例2、String類
#include<iostream>
#include<string.h>
#include<assert.h>
using namespace std;
class String;
ostream& operator<<(ostream &out, const String &str);
class String{
friend ostream& operator<<(ostream &out, const String &str);
public:
String(const char *str = ""){
if(str == NULL){
data = new char[1];
data[0] = 0;
}else{
data = new char[strlen(str) + 1];
strcpy(data, str);
}
}
//String(const String &str){}
String& operator=(const String &str){
if(this != &str){
delete []data;
data = new char[strlen(str.data) + 1];
strcpy(data, str.data);
}
return *this;
}
~String(){
delete []data;
}
public:
String operator+(const String &str){
char *tmp;
tmp = new char[strlen(data) + strlen(str.data) + 1];
strcpy(tmp, data);
strcat(tmp, str.data);
return String(tmp);
}
void operator+=(const String &str){
char *new_data = new char[strlen(data) + strlen(str.data) + 1];
strcpy(new_data, data);
strcat(new_data, str.data);
delete []data;
data = new_data;
/*
realloc(data, strlen(data) + strlen(str.data) + 1); //此時對原有的數組空間進行動态擴長,
// 給誰擴長 加上原先,一共要有多長 即原有值不變。
strcat(data, str.data);
*/
}
char operator[](int pos){
assert(pos >= 0 && pos < strlen(data));
return data[pos];
}
char operator*(){
return data[0];
}
bool operator==(const String &str){
return strcmp(data, str.data) ? false : true;
}
bool operator!=(const String &str){
return !(*this == str); //調用==這個編寫過的函數
}
private:
char *data;
};
ostream& operator<<(ostream &out, const String &str){
out<<str.data;
return out;
}
int main(void){
String s1("hello");
String s2("world");
String s3;
s3 = s1 + s2;
cout<<s3<<endl;
s1 += s2;
cout<<s1<<endl;
cout<<s1[1]<<endl;
cout<<*s1<<endl;
if(s1 == s3){
cout<<"相等"<<endl;
}else{
cout<<"不相等"<<endl;
}
if(s1 != s3){
cout<<"不相等"<<endl;
}else{
cout<<"相等"<<endl;
}
return 0;
}
對其+,+=,[],*,==,!=進行了運算符的重載,結果如下:
3、const和static
在C++中const是非常重要的,現在說明常函數之間的關系:普通函數可以調用常函數,常函數不能調用普通函數(因為沒有this);
void fun()const{}
void fun(){} //一個有const,一個沒有,參數類型不一樣,是以這是函數的重載!
static在C++中有成員和方法,靜态成員的在類外初始化;類的靜态成員為所有對象所共享。
靜态方法: (1)、可以調用該類的私有成員,(2)、應該位于類的作用域之中;(3)、類名直接調用,可以不用方法;