1. 程式人生 > >C++之引用&過載

C++之引用&過載


1.引用(reference )的概念:      引用是一個目標的別名;目標可以是變數或物件; 2.宣告引用的符號為&,引用開始必須初始化;(將引用與一個目標進行繫結); 3.操作引用就是操作目標本身,反之亦然; 4.一個目標可以有多個引用;(就像一個人可以有多個別名一樣) 5.一個引用不能同時繫結多個目標; 6.有指標的引用,例如:int *&t_p1 = t_p2; 7.沒有陣列的引用,沒有void引用;但是可以有引用的陣列 8.引用的型別必須和目標的型別一樣; 9.常引用(const引用):作用不能通過const引用來修改被繫結目標的值; int t_a = 200; int t_b = 300;
const int &t_c = t_a; //t_c = 400; is error , t_c read-only reference   t_a = 400;
10.引用作為函式的引數的好處:減少拷貝,提高效率; 11.引用作為函式的返回值的好處:減少一次拷貝,提高效率;注意當函式的返回值為引用型別時,不要將一個臨時變數返回出去; 12.行內函數:1~5行的程式碼量的小函式適合作為行內函數;原理就是程式碼替換 好處:提高程式碼的執行效率,以時間換空間; 行內函數的宣告和定義必須放在一個檔案裡inline關鍵字是建議C++編譯器將該函式搞為行內函數,但沒有決定權;當函式裡面有迴圈語句,複雜的條件語句,遞迴等,則C++編譯器無視inline關鍵字,將該函式作為普通函式處理;
13.函式過載:滿足函式過載的條件,有相同的函式名,不同的形參列表;與函式的返回值無關;如果該函式有預設引數,則過載該函式的時候,需要特別注意; 14.遞迴函式:自己呼叫自己的函式,注意必須要有退出函式的條件判斷; 15.函式的預設引數:函式可以有自己的預設引數,例如int add(int t_a = 10,int t_b = 20,int t_c = 30, int t_d = 40); 如果這樣呼叫add(),則引數全部用的是預設值10,20,30,40; 如果是這樣呼叫add(50),則後面3個引數用預設的20,30,40,依次類推;注意我們給函式增加預設引數時,必須從右往左新增,例如int add(int t_a,int t_b,int t_c,int t_d = 10)
是正確的,而int add(int t_a = 30,int t_b,int t_c,int t_d)是錯誤的,編譯不過,因為當傳遞實參時,編譯器會自左向右與形參進行匹配。例如add(1,2,3)這樣傳參的話,則t_a=1,t_b=2,t_c=3,那t_d就沒有值了,那這種情況下就必須傳遞4個引數,而這樣又違背了預設引數的初衷,初衷是可以傳遞3個引數的;所以編譯器不允許程式設計師這麼做,因為這麼做函式預設引數就毫無意義了。
16.關於函式傳參的總結:基本型別(int,char,double),列舉型別一般用值傳遞,結構/類的物件一般用引用或指標傳遞,陣列型別一般用指標傳遞; 17.形參是引用傳遞時,一般將形參設定為const型別的引用,這樣的好處是防止在函式中誤操作,將實參的值修改了; 練習: 設計一個函式,函式的返回值為引用,返回兩個字串中長度最大的字串; const string& maxString(const string &t_str1, const string &t_str2) {     return t_str1.length() > t_str2.length()  ?  t_str1 : t_str2; } 錯誤示例: 1.宣告引用時沒有初始化,在qt編譯器下,有如下警報: D:\QQPCmgr\Desktop\C++_Prj\Reference\main.cpp:10: 錯誤:'t_c' declared as reference but not initialized 在Linux下g++編譯器的錯誤提示: reference.cpp:9:7: error: ‘t_c’ declared as reference but not initialized

引用就是某一個變數的別名,引用的地址就是原變數的地址,引用的值就是原變數的值

不能建立引用的陣列,例如:int & ref[3] = { 2, 3, 5}; //宣告ref引用的陣列是錯誤的

但是可以建立陣列的引用:例如:int arr[3]; int (&tef)[3] = arr; //這是這是正確的

為什麼陣列中的元素不能是引用?

c++中,引用可以說只是某個變數的別名,所謂別名,是和指標型別區分開的:      指標型別也可以指向某個變數,但指標型別本身也是一個變數,而引用實際上不是一個變數。更本質來說,可以理解為引用沒有自身的地址,不佔用記憶體空間(這裡為了簡化問題可以這樣考慮)。因此,宣告引用陣列沒有辦法分配空間,因為根本就沒有空間可以分配給引用。所以不能宣告和定義引用陣列 函式過載(overload):將語義,功能相似的幾個函式用同一個名字來表示 易用性 建構函式需要過載機制,c++規定建構函式與類同名,且只能有一個名字 規則: 由函式介面(引數,返回值)區別過載函式,顯然,返回值無法讓編譯器和程式設計師知道哪個函式被呼叫,因為c/c++中返回值有時可悲忽略! 假設某個c函式如下: void foo(int x, int y);      該函式在c編譯器編譯後在庫中的名字為_foo,而c++編譯器則會產生_foo_int_int之類的名字用來支援函式過載和型別安全連線。由於編譯後的名字不同,故然c++不能直接呼叫c函式。 提供了一個c連線交換指定符號extern “C” 注意: 並不是兩個函式的名字相同就構成函式過載,全域性函式和成員函式同名不算過載,不在同一作用域! 全域性函式被呼叫是要加上域作用符“::” 隱式型別轉換會導致過載函式產生二義性 成員函式被過載的特徵:      1.相同的範圍(在同一類中)      2.函式名字相同      3.引數不同      4.virtual關鍵字可有可無 覆蓋是指派生類函式覆蓋基類函式,特徵是: 1)不同的範圍(分別位於派生類與基類); 2)函式名字相同; 3)引數相同; 4)基類函式必須有virtual 關鍵字。

程式碼示例:

//comdef.h(在include資料夾裡,makefile中要包含路徑)

#ifndef _COMDEF_H_
#define _COMDEF_H_

#ifdef _cplusplus
extern "C"
{
#endif

	extern void mySwap(int *a, int *b);

#ifdef _cplusplus
}
#endif

#include <cmath>

#define PI acos(-1.0)


#endif



Makefile檔案:
GOAL := overload_implicit

objs := ${GOAL}.o 

CFLAGS := -I${shell pwd}/include

CPP := g++

${GOAL} : ${objs}
	g++ $^ -o [email protected] -lm

export CFLAGS CPP

%.o : %.cpp
	${CPP} ${CFLAGS} -Wall -fpermissive -c $^ -o [email protected]

.PHONY: clean
clean:
	rm -rf ${GOAL} *.


//<strong><span style="font-size: 19px;"></span></strong>overload_implicit.cpp

#include <iostream>

using namespace std;

void output(int n);
void output(float n);

void output(int n)
{
	cout << "output int: " << n << endl;
}

void output(float n)
{
	cout << "output float: " << n << endl;
}

int main(void)
{
	int x = 1;
	float y = 1.0;

	output(x);
	output(y);

	output(1);

	return 0;
}

//overload_swap.cpp

#include <iostream>
#include <string>
#include <cstring>
#include "comdef.h"

using namespace std;

double g_area;

void Print()
{
	cout << "global function" << endl;
}

class A
{
public:
	void Print()
	{
		cout << "member function\n";
	}
};

void mySwap(int *a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void mySwap(int &t_a, int &t_b)
{
	int tmp = t_a;
	t_a = t_b;
	t_b = tmp;
}

const string& maxString(const string &t_str1, const string &t_str2)
{
	return t_str1.length() > t_str2.length() ? t_str1 : t_str2;
}

double &getArea(double t_r)
{
	g_area = PI * t_r * t_r;

	return g_area;
}

int main(void)
{
	cout << "pi = " << PI << endl;

	int t_a = 100, t_b = 200;

	cout << "t_a = " << t_a << ", t_b = " << t_b << endl;

#if 0
	cout << "point swap\n";
	mySwap(&t_a, &t_b);

	cout << "t_a = " << t_a << ", t_b = " << t_b << endl;
#endif

	cout << "reference swap\n";
	mySwap(t_a, t_b);
	cout << "t_a = " << t_a << ", t_b = " << t_b << endl;

	double t_r = 10.0;

	double &t_area = getArea(t_r);

	cout << "area: " << t_area << endl;

	string t_str1 = "hello";
	string t_str2 = "world";

	cout << "The Max string 'hello' and 'word' is : " << maxString(t_str1, t_str2) << endl;

	cout << "=============================\n";

	::Print();

	return 0;
}

//reference.cpp

#include <iostream>
#include <string>

using namespace std;

struct animal
{
	string m_name;
	int m_weight;
	int m_age;
};

void getAnimalInfo(const animal &t_animal)
{
	cout << "animal name: " << t_animal.m_name << endl;
	cout << "animal weight: " << t_animal.m_weight << endl;
	cout << "animal age: " << t_animal.m_age << endl;
}

void setAnimalInfo(animal &t_animal)
{
	cout << "Please input the animal name: \n";
	cin >> t_animal.m_name;
	cout << "Please input the animal weight: \n";
	cin >> t_animal.m_weight;
	cout << "Please input the animal age: \n";
	cin >> t_animal.m_age;
}

void setAnimalInfo(animal &t_animal, const string &t_name, int t_weight, int t_age)
{
	t_animal.m_name = t_name;
	t_animal.m_weight = t_weight;
	t_animal.m_age = t_age;
}

void setAnimalInfo(animal &t_destAnimal, const animal &t_srcAnimal)
{
	t_destAnimal.m_name = t_srcAnimal.m_name;
	t_destAnimal.m_weight = t_srcAnimal.m_weight;
	t_destAnimal.m_age = t_srcAnimal.m_age;
}

int main(int argc, char *argv[])
{
	int t_a = 200, t_b = 300;
	
	const int &t_c = t_a;

	t_a = t_b;

	cout << "&t_a = " << &t_a << "	t_a = " << t_a << endl;
	cout << "&t_c = " << &t_c << "	t_c = " << t_c << endl;

	animal t_animal = {"Tiger", 200, 5};
	getAnimalInfo(t_animal);
	setAnimalInfo(t_animal, "Dog", 100, 10);
	getAnimalInfo(t_animal);

	return 0;
}






#ifndefFUN2_H
#defineFUN2_H
//函式過載
//1.函式名一樣 2.函式的形參列表不一樣 3.與函式的返回值無關
voidSwap(int*t_p1,int*t_p2);
voidSwap(int&t_x,int&t_y);
voidSwap(int&t_x,int&t_y,boolt_b);
//增加函式的預設引數,必須從右往左新增
//函式傳參時,實參匹配形參的順序是從左往右的
intadd(intt_a,intt_b,intt_c,intt_d=4);
#endif// FUN2_H

相關推薦

C++引用&過載

1.引用(reference )的概念:      引用是一個目標的別名;目標可以是變數或物件; 2.宣告引用的符號為&,引用開始必須初始化;(將引用與一個目標進行繫結); 3.操作引用就是操

C++引用&的詳解

ID 發生 AS res 函數返回 clas -c AD 數組 C++中的引用: 引用引入了對象的一個同義詞。定義引用的表示方法與定義指針相似,只是用&代替了*。引用(reference)是c++對c語言的重要擴充。引用就是某一變量(目標)的一個別名,對引用的操作與

C++引用

() 關系型 tmp 內存地址 指針變量 返回 分配內存 多次 amp 目錄 C++之引用 1、什麽是引用 2、為何引入引用 3、引用的規則 4、變量的引用及舉例 4.3、數組變量的引用 5、常引用及舉例(關鍵字const) C++之引用 1、什麽是引用 引用,就是

C++引用與符號“&”

按位與 改變 聲明 str 使用 直接 進行 意思 other 一、&的意思: 1.取地址符,這時候它用於數據的前面,比如int a=&b; 2.C++裏還使用&作為引用符,如果你確認程序是標準的C而非C++的話,那麽可以排除是引用了。引用也

初識C++函式過載、重寫、重定義的區別

在C++的學習中,慢慢接觸了一些很容易混淆的名詞,今天就來剖析幾個容易混淆的名詞。 1、函式過載   過載函式是函式的一種特殊情況,為方便使用,C++允許在同一範圍中宣告幾個功能類似的同名函式,但是這些同名函式的形式引數(指引數的個數、型別或者順序)必須不同

c++引用和指標的區別和聯絡

區別: 1 引用不能為空(必須初始化),指標可為空。 int &a; // error int *a; // ok 2 引用關係一旦被建立,則不能被解除,而指標可以指向別人。 int x = 1, y = 2; int &a = x; a = y;

c# 第9節 數據類型引用類型

類型 數據 分享 bubuko 賦值 OS http pos 字符 本節內容: 1:數據類型之引用類型 2:字符串要註意的兩點: 1:數據類型之引用類型 實例: 2:字符串要註意的兩點: 對變量進行重新賦值:其原本的字符串並沒有銷毀

c++入門引用

引用通常被用在函式形參傳遞的過程中。一般的引數傳遞的過程:將實參進行拷貝,函式中都是對拷貝的變數進行操作,而不是對原變數進行操作。但很多情況下,我們都希望對原變數進行操作.(比如交換兩個變數的數值)。下面先給出一段程式碼: 1 #include "iostream" 2 #include "str

C++過載運算子

C++過載運算子 過載運算子 C++中很多內建資料型別都支援如"+"、"-"、"="、"<"等運算子,這使得表示式非常的簡潔。但很多情況下,我們也希望自已定義的一些資料結構也支援類似的運算子。C++提供了這樣一種機制,支援我們在不同的資料型別下對運算子進行過

C++不同物件的成員函式如何引用指定物件的資料成員

C++成員函式儲存問題點選開啟連結 可知C++成員函式不佔用物件的儲存空間,而是在物件外的空間,而且所有物件共用一段成員函式程式碼,那在不同物件的成員函式如何保證引用指定物件的資料成員呢? 關鍵祕籍——this指標    

C++過載陣列下標[]與圓括號()運算子的方法

#include <iostream> using namespace std; class Matrix { public: Matrix(int, int) ; int& operator()(int, int) ; // 過載圓括號運算子"()" private:

【轉】c++右值引用

從左值右值到右值引用 地址:https://www.cnblogs.com/inevermore/p/4029753.html C++98中規定了左值和右值的概念,但是一般程式設計師不需要理解的過於深入,因為對於C++98,左值和右值的劃分一般用處不大,但是到了C++11,它的重要性

混跡於C++ 過載與覆蓋(還有隱藏)

摘自《高質量程式設計指南》林銳 過載與覆蓋 成員函式被過載的特徵是: -具有相同的作用域(即同一個類定義中)--如果位於不同的作用域,則為隱藏。 -函式名字相同。 -引數型別/順序或數目不同(包括const引數和非const引數)。 -virtual關鍵字可有可無。 覆蓋是

C#基礎知識函式過載OverLoad

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Over

C++ 基礎 "引用形參" 和 "利用const引用避免複製" &

之前兩篇文章裡的兩個函式如下所示: //過載操作符+ Vector3 operator+(const Vector3 &a){ return Vector3(x + a.x,y + a.y,z+a.z); } //比較兩

C++引用:經典例題引用作為函式的返回值,結合函式棧幀詳解

程式碼如下: #include <stdio.h> #include <windows.h> #include <iostream> using namespa

C++學習引用特性

引用即給變數賦予一個別名,就像外號一樣,我叫李曉明,外號小明,實際都是指李曉明這個人。 #include<iostream> using namespace std; int main() { //C++中的引用 int a = 3; int &

C++拷貝建構函式和複製運算子過載

1、C++拷貝建構函式 拷貝建構函式是為了解決如神明物件時候就用一個已經存在的物件來初始化這個新的物件,如MyString A(B):這裡B是已經存在MyString物件。但是這裡需要注意拷貝建構函式裡面的內部實現細節。這裡面其實是在這個A物件類的定義中定義了拷貝建構函式的

C++過載函式

過載函式的定義: 用同一個函式名定義不同的函式 當函式名和不同的引數搭配時函式的含義不同 過載函式的判斷標準: 函式過載至少滿足下面的一個條件: 引數個數不同 引數型

java——與c++不同——複合型別——指標 引用 struct union

指標 不支援,因此java不支援以下運算子: 取地址運算子(&)取內容運算子(*)(指標)成員運算子(->)引用 java支援引用,引用可理解為功能限縮的指標,僅支援指標的部分比較運算子