目錄
- 1、用類創建對象
- 1、面向對象的特征
- 2、對象由什么構成
- 3、如何定義對象
- 4、創建對象并訪問對象成員
- 1. Constructors(構造函數)
- 2. Constructing Objects (創建對象)
- 3. Object Member Access Operator(對象訪問運算符)
- 2、對象拷貝以及分離聲明與實現
- 1、類是一種數據類型
- 1.1. 定義變量的例子:
- 1.2. 定義對象的例子:
- 2. Memberwise Copy (成員拷貝)
- 3、匿名對象
- 4、局部類和嵌套類
- 5、question-是否存在匿名對象?
- 3、Separating Declaration from Implementation
- 1、C中的用法
- 2、Separating Declaration from Implementation
- 3、Inline Declaration & Inline Function
- 4、注意事項
- 4、避免頭文件被多次包含
1、用類創建對象
1、面向對象的特征
(1) Abstraction (抽象)
(2) Polymorphism (多態)
(3) Inheritance (繼承)
(4) Encapsulation (封裝)
2、對象由什么構成
對象具有唯一的標識、狀態和行為。
對象狀態由數據域(也稱為“屬性”)及其當前值構成。
對象的行為由一組函數定義。
3、如何定義對象
對象是類的實例。
類包含:
1、由變量定義的數據域
2、由函數定義的行為
類中有兩種特殊的函數:
constructors : (構造函數:在創建對象時被自動調用)
destructors : (析構函數:在對象被銷毀時被自動調用)
4、創建對象并訪問對象成員
1. Constructors(構造函數)
class Circle {
public:// The radius of this circledouble radius;// Construct a circle objectCircle() {radius = 1;}// Construct a circle objectCircle(double newRadius) {radius = newRadius;}// Return the area of this circledouble getArea() {return radius * radius * 3.14159;}
};
Ctors的特點:
(1) Automatic invocation(自動調用)
(2) Has the same name as the defining class (與類同名)
(3) NO return value (including “void”);(無返回值)
(4) Can be overloaded (可重載)
(5) May have no arguments (可不帶參數)
類可不聲明構造函數,編譯器會提供一個帶有空函數體的無參構造函數,只有當未明確聲明構造函數時,編譯器才會提供這個構造函數,并稱之為“默認構造函數”。
2. Constructing Objects (創建對象)
Circle circle1; // 正確,但不推薦這樣寫
Circle circle2(); // 錯誤!C++編譯器認為這是一個函數聲明
Circle circle3{}; // 正確,推薦寫法。這里面明確顯示用空初始化列表初始化circle3對象(調用Circle默認構造函數)Circle circle2{ 5.5 }; // C++11 列表初始化// 帶有窄化檢查(narrowing check)
3. Object Member Access Operator(對象訪問運算符)
#include <iostream>
using namespace std;
class Circle {
public:// The radius of this circledouble radius;// Construct a circle objectCircle() {radius = 1;}// Construct a circle objectCircle(double newRadius) {radius = newRadius;}// Return the area of this circledouble getArea() {return radius * radius * 3.14159;}
};int main() {Circle circle1;Circle circle2(5.0);cout << "The area of the circle of radius " <<circle1.radius << " is " << circle1.getArea() << endl;cout << "The area of the circle of radius " <<circle2.radius << " is " << circle2.getArea() << endl;// Modify circle radiuscircle2.radius = 100.0;cout << "The area of the circle of radius " <<circle2.radius << " is " << circle2.getArea() << endl;return 0;
}
2、對象拷貝以及分離聲明與實現
用類聲明一個實體的說法,與定義變量的說法有些不同:用原生數據類型定義變量,用類名定義對象。
1、類是一種數據類型
1.1. 定義變量的例子:
// primitive data type è variablesdouble d1; //未初始化double d2(3.3); int x1{2.0}; //error: Narrowingint x2={4};auto i{x};decltype(d1) j;
1.2. 定義對象的例子:
// class è objectsCircle c1; //調用Circle的默認ctorCircle c2(5.5); //調用Circle的有參ctorCircle c3{5.5}; // 直接列表初始化,調有參ctorCircle c4 = {5.5}; // 拷貝列表初始化,調ctorauto c5 = Circle{2.}; // auto類型推斷decltype(c1) c6; // decltype類型推斷
2. Memberwise Copy (成員拷貝)
1、使用賦值運算符: =
2、默認情況下,對象中的每個數據域都被拷貝到另一對象的對應部分
circle2 = circle1;
(1) 將circle1 的radius 拷貝到circle2 中
(2) 拷貝后:circle1 和 circle2 是兩個不同的對象,但是半徑的值是相同的。( 但是各自有一個radius 成員變量)
3、匿名對象
Occasionally, you may create an object and use it only once. (有時需要創建一個只用一次的對象)
An object without name is called anonymous objects. (這種不命名的對象叫做匿名對象)
Example
int main() {Circle c1 = Circle{1.1};auto c2 = Circle{2.2}; // 用匿名對象做拷貝列表初始化Circle c3{}; // 直接列表初始化,調默認Ctorc3 = Circle{3.3}; // 用匿名對象賦值cout << "Area is " << Circle{4.2}.getArea() << endl;cout << "Area is " << Circle().getArea() << endl; // 不推薦cout << "Area is " << Circle(5).getArea() << endl; // 不推薦return 0;
}
4、局部類和嵌套類
Local class : a class declared inside a function (局部類是在一個函數中聲明的類)
void f(){class C { // C及其對象只在f()中可用 void g() { // 成員函數必須在C中實現/* 訪問f()的成員受限 ……. */}};C c1, c2;
}
Nested class: a class declared in another enclosing class (嵌套類是在另一個類中聲明的類)
class E{class N { // N及其對象可訪問E的成員 /* 聲明N的成員 ……. */}};C c1, c2;}
5、question-是否存在匿名對象?
question description:
Circle類接受一個double參數構造其對象,那么
Circle c1 = { 1.0 };
Circle c2 = Circle {1.0};
這兩條語句的執行結果是相同的,c1和c2都是一個半徑為1.0的圓對象。
但是,這兩條語句執行過程是否一樣呢?第一條語句的等號右側是否也構造了一個匿名對象呢?
兩者的執行結果是一樣的,都是將c1和c2對象的半徑賦值1.0。
但是執行過程是不一樣的,c1是通過拷貝列表初始化的方式賦值;c2是通過匿名對象拷貝的方式賦值。
3、Separating Declaration from Implementation
在聲明之后,定義之前,類為不完整類型,只能用于指向該類型的指針或者引用或者
用于聲明使用該類型作為形參類型或者返回類型的函數。
解決方法:
1、將函數的實現放在類聲明的最下面
2、將類的聲明放在一個頭文件中,類的實現放在另一個文件中。
1、C中的用法
// GetArea.h:
float getArea (float radius);// GetArea.cpp:
#include "GetArea.h"
float getArea (float radius) {return radius*radius*3.14;
}
//main.c:
#include "GetArea.h"
int main() {int result=getArea(2.0;return 0;
}
2、Separating Declaration from Implementation
(1) .h: 類聲明,描述類的結構
(2) .cpp: 類實現,描述類方法的實現
FunctionType ClassName :: FunctionName (Arguments) { //… }
其中,:: 這個運算符被稱為binary scope resolution operator(二元作用域解析運算符),簡稱“域分隔符”
Circle.h
//Circle.h
class Circle{double radius;
public:Circle();Circle(double radius_);double getArea();
};
Circle.cpp
Circle::Circle(){radius=1.0;
}
Circle::Circle(double radius_){radius=radius_;
}
double Circle::getArea(){return (3.14 * radius * radius);
}
main.cpp
//main.cpp
int main(){Circle c1;Circle c2 {2.0};std::cout << c1.getArea() << std::endl;return 0;
}
3、Inline Declaration & Inline Function
1、當函數在類聲明中實現,它自動成為內聯函數
class A {
public:A() = default; //C++11,編譯器識別后一定會生成一個默認的構造函數double f1() { // f1自動稱為內聯函數// do something} double f2();
};
double A::f2() { // f2不是內聯函數//do something}
2、當函數在類的外部實現,加上inline也會成為內聯函數
class A {
public:A() = default; //C++11double f1();double f2();
};
double A::f2() {//do something
}
inline double A::f1() { // f1是內聯函數//do something
}
4、注意事項
1. //a.h
2. void f();
3.
4. // a.cpp
5. #include "a.h"
6. void f() {}
7.
8. //main.cpp
9. #include "a.h"
10. void f() {}
第6行和第10行構成了語法錯誤:重定義函數
但是 Compiler 不報錯,這個錯誤只能在link階段才能檢測出來。
4、避免頭文件被多次包含
例1:
#ifndef MY_HEADER_FILE_H#define MY_HEADER_FILE_H// 頭文件內容#endif
例2:
#pragma once // C++03, C90
例3
_Pragma("once") // C++11, C99; _Pragma是一個運算符