【C++ grammar】对象和类(创建对象、对象拷贝、分离声明与实现)
目錄
- 1、用類(lèi)創(chuàng)建對(duì)象
- 1、面向?qū)ο蟮奶卣?/li>
- 2、對(duì)象由什么構(gòu)成
- 3、如何定義對(duì)象
- 4、創(chuàng)建對(duì)象并訪問(wèn)對(duì)象成員
- 1. Constructors(構(gòu)造函數(shù))
- 2. Constructing Objects (創(chuàng)建對(duì)象)
- 3. Object Member Access Operator(對(duì)象訪問(wèn)運(yùn)算符)
- 2、對(duì)象拷貝以及分離聲明與實(shí)現(xiàn)
- 1、類(lèi)是一種數(shù)據(jù)類(lèi)型
- 1.1. 定義變量的例子:
- 1.2. 定義對(duì)象的例子:
- 2. Memberwise Copy (成員拷貝)
- 3、匿名對(duì)象
- 4、局部類(lèi)和嵌套類(lèi)
- 5、question-是否存在匿名對(duì)象?
- 3、Separating Declaration from Implementation
- 1、C中的用法
- 2、Separating Declaration from Implementation
- 3、Inline Declaration & Inline Function
- 4、注意事項(xiàng)
- 4、避免頭文件被多次包含
1、用類(lèi)創(chuàng)建對(duì)象
1、面向?qū)ο蟮奶卣?/h2>
(1) Abstraction (抽象)
(2) Polymorphism (多態(tài))
(3) Inheritance (繼承)
(4) Encapsulation (封裝)
2、對(duì)象由什么構(gòu)成
對(duì)象具有唯一的標(biāo)識(shí)、狀態(tài)和行為。
對(duì)象狀態(tài)由數(shù)據(jù)域(也稱(chēng)為“屬性”)及其當(dāng)前值構(gòu)成。
對(duì)象的行為由一組函數(shù)定義。
3、如何定義對(duì)象
對(duì)象是類(lèi)的實(shí)例。
類(lèi)包含:
1、由變量定義的數(shù)據(jù)域
2、由函數(shù)定義的行為
類(lèi)中有兩種特殊的函數(shù):
constructors : (構(gòu)造函數(shù):在創(chuàng)建對(duì)象時(shí)被自動(dòng)調(diào)用)
destructors : (析構(gòu)函數(shù):在對(duì)象被銷(xiāo)毀時(shí)被自動(dòng)調(diào)用)
4、創(chuàng)建對(duì)象并訪問(wèn)對(duì)象成員
1. Constructors(構(gòu)造函數(shù))
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的特點(diǎn):
(1) Automatic invocation(自動(dòng)調(diào)用)
(2) Has the same name as the defining class (與類(lèi)同名)
(3) NO return value (including “void”);(無(wú)返回值)
(4) Can be overloaded (可重載)
(5) May have no arguments (可不帶參數(shù))
類(lèi)可不聲明構(gòu)造函數(shù),編譯器會(huì)提供一個(gè)帶有空函數(shù)體的無(wú)參構(gòu)造函數(shù),只有當(dāng)未明確聲明構(gòu)造函數(shù)時(shí),編譯器才會(huì)提供這個(gè)構(gòu)造函數(shù),并稱(chēng)之為“默認(rèn)構(gòu)造函數(shù)”。
2. Constructing Objects (創(chuàng)建對(duì)象)
Circle circle1; // 正確,但不推薦這樣寫(xiě) Circle circle2(); // 錯(cuò)誤!C++編譯器認(rèn)為這是一個(gè)函數(shù)聲明 Circle circle3{}; // 正確,推薦寫(xiě)法。這里面明確顯示用空初始化列表初始化circle3對(duì)象(調(diào)用Circle默認(rèn)構(gòu)造函數(shù))Circle circle2{ 5.5 }; // C++11 列表初始化// 帶有窄化檢查(narrowing check)3. Object Member Access Operator(對(duì)象訪問(wèn)運(yùn)算符)
#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、對(duì)象拷貝以及分離聲明與實(shí)現(xiàn)
用類(lèi)聲明一個(gè)實(shí)體的說(shuō)法,與定義變量的說(shuō)法有些不同:用原生數(shù)據(jù)類(lèi)型定義變量,用類(lèi)名定義對(duì)象。
1、類(lèi)是一種數(shù)據(jù)類(lèi)型
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. 定義對(duì)象的例子:
// class è objectsCircle c1; //調(diào)用Circle的默認(rèn)ctorCircle c2(5.5); //調(diào)用Circle的有參ctorCircle c3{5.5}; // 直接列表初始化,調(diào)有參ctorCircle c4 = {5.5}; // 拷貝列表初始化,調(diào)ctorauto c5 = Circle{2.}; // auto類(lèi)型推斷decltype(c1) c6; // decltype類(lèi)型推斷2. Memberwise Copy (成員拷貝)
1、使用賦值運(yùn)算符: =
2、默認(rèn)情況下,對(duì)象中的每個(gè)數(shù)據(jù)域都被拷貝到另一對(duì)象的對(duì)應(yīng)部分
circle2 = circle1;
(1) 將circle1 的radius 拷貝到circle2 中
(2) 拷貝后:circle1 和 circle2 是兩個(gè)不同的對(duì)象,但是半徑的值是相同的。( 但是各自有一個(gè)radius 成員變量)
3、匿名對(duì)象
Occasionally, you may create an object and use it only once. (有時(shí)需要?jiǎng)?chuàng)建一個(gè)只用一次的對(duì)象)
An object without name is called anonymous objects. (這種不命名的對(duì)象叫做匿名對(duì)象)
Example
int main() {Circle c1 = Circle{1.1};auto c2 = Circle{2.2}; // 用匿名對(duì)象做拷貝列表初始化Circle c3{}; // 直接列表初始化,調(diào)默認(rèn)Ctorc3 = Circle{3.3}; // 用匿名對(duì)象賦值cout << "Area is " << Circle{4.2}.getArea() << endl;cout << "Area is " << Circle().getArea() << endl; // 不推薦cout << "Area is " << Circle(5).getArea() << endl; // 不推薦return 0; }4、局部類(lèi)和嵌套類(lèi)
Local class : a class declared inside a function (局部類(lèi)是在一個(gè)函數(shù)中聲明的類(lèi))
void f(){class C { // C及其對(duì)象只在f()中可用 void g() { // 成員函數(shù)必須在C中實(shí)現(xiàn)/* 訪問(wèn)f()的成員受限 ……. */}};C c1, c2; }Nested class: a class declared in another enclosing class (嵌套類(lèi)是在另一個(gè)類(lèi)中聲明的類(lèi))
class E{class N { // N及其對(duì)象可訪問(wèn)E的成員 /* 聲明N的成員 ……. */}};C c1, c2;}5、question-是否存在匿名對(duì)象?
question description:
Circle類(lèi)接受一個(gè)double參數(shù)構(gòu)造其對(duì)象,那么
這兩條語(yǔ)句的執(zhí)行結(jié)果是相同的,c1和c2都是一個(gè)半徑為1.0的圓對(duì)象。
但是,這兩條語(yǔ)句執(zhí)行過(guò)程是否一樣呢?第一條語(yǔ)句的等號(hào)右側(cè)是否也構(gòu)造了一個(gè)匿名對(duì)象呢?
兩者的執(zhí)行結(jié)果是一樣的,都是將c1和c2對(duì)象的半徑賦值1.0。
但是執(zhí)行過(guò)程是不一樣的,c1是通過(guò)拷貝列表初始化的方式賦值;c2是通過(guò)匿名對(duì)象拷貝的方式賦值。
3、Separating Declaration from Implementation
在聲明之后,定義之前,類(lèi)為不完整類(lèi)型,只能用于指向該類(lèi)型的指針或者引用或者
用于聲明使用該類(lèi)型作為形參類(lèi)型或者返回類(lèi)型的函數(shù)。
解決方法:
1、將函數(shù)的實(shí)現(xiàn)放在類(lèi)聲明的最下面
2、將類(lèi)的聲明放在一個(gè)頭文件中,類(lèi)的實(shí)現(xiàn)放在另一個(gè)文件中。
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: 類(lèi)聲明,描述類(lèi)的結(jié)構(gòu)
(2) .cpp: 類(lèi)實(shí)現(xiàn),描述類(lèi)方法的實(shí)現(xiàn)
FunctionType ClassName :: FunctionName (Arguments) { //… }
其中,:: 這個(gè)運(yùn)算符被稱(chēng)為binary scope resolution operator(二元作用域解析運(yùn)算符),簡(jiǎn)稱(chēng)“域分隔符”
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、當(dāng)函數(shù)在類(lèi)聲明中實(shí)現(xiàn),它自動(dòng)成為內(nèi)聯(lián)函數(shù)
class A { public:A() = default; //C++11,編譯器識(shí)別后一定會(huì)生成一個(gè)默認(rèn)的構(gòu)造函數(shù)double f1() { // f1自動(dòng)稱(chēng)為內(nèi)聯(lián)函數(shù)// do something} double f2(); }; double A::f2() { // f2不是內(nèi)聯(lián)函數(shù)//do something}2、當(dāng)函數(shù)在類(lèi)的外部實(shí)現(xiàn),加上inline也會(huì)成為內(nèi)聯(lián)函數(shù)
class A { public:A() = default; //C++11double f1();double f2(); }; double A::f2() {//do something } inline double A::f1() { // f1是內(nèi)聯(lián)函數(shù)//do something }4、注意事項(xiàng)
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行構(gòu)成了語(yǔ)法錯(cuò)誤:重定義函數(shù)
但是 Compiler 不報(bào)錯(cuò),這個(gè)錯(cuò)誤只能在link階段才能檢測(cè)出來(lái)。
4、避免頭文件被多次包含
例1:
#ifndef MY_HEADER_FILE_H#define MY_HEADER_FILE_H// 頭文件內(nèi)容#endif例2:
#pragma once // C++03, C90例3
_Pragma("once") // C++11, C99; _Pragma是一個(gè)運(yùn)算符總結(jié)
以上是生活随笔為你收集整理的【C++ grammar】对象和类(创建对象、对象拷贝、分离声明与实现)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: LeetCode 二叉树、N叉树的最大深
- 下一篇: 【C++ grammar】对象指针、对象