日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C++:随笔6---new\delete\虚方法\抽象方法

發布時間:2023/11/27 生活经验 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++:随笔6---new\delete\虚方法\抽象方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

指針是一種專門用來存儲內存地址的數據類型。(他存儲的不是具體的數據而是別人的地址)

常用做法是:創建一個變量,再把這個變量的地址賦值給一個指針,然后就可以用指針去訪問這個變量的值。

事實上在C和C++中,我們完全可以在沒有創建變量的情況下,為有關數據分配內存,也就是直接創建一個指針,并讓她指向新分配的內存塊。

int *pointer=new int;//int *pointer表示一個指向整型變量的指針,指針的名字叫做pointer,我們用new給他創建一個內存這個內存是什么類型呢?是int型。(整型的內存在現在的編譯器一般是占用了4個字節的內存空間,那么這樣定義的語句就是說聲明一個指針變量,這個指針變量的名字叫做pointer,它指向一個整型的地址空間,用new給他創建出來,new事實上就是那個malloc這個函數的一個進化版本,都是差不多的只是對他進行了進一步的封裝而已)
*pointer=110;//接著給這個指針,就是new出來的這塊內存給他賦值,賦值為110
std::cout<<*pointer;//使用這個指針變量的值把他給打印出來
delete pointer;//最后刪除這個指針,也就是釋放了這一塊new出來的內存。
//最后一步是非常必要和關鍵的,這是因為C和C++程序不會自動釋放內存,程序中的每一個new操作都必須有一個與之對應的delete操作。

創建對象有兩種寫法,一種就是這里的如下,一種就是使用?new。

就死記住,語法這樣寫:

類?對象?(參數);//括號內的參數會自動調用構造函數對這個類進行初始化。

http://c.biancheng.net/view/2221.html

#include<string>
#include<iostream>class Pet
{
public:Pet(std::string theName);//構造函數void eat();void sleep();void play();
protected:std::string name;
};
class Cat :public Pet
{
public:Cat(std::string theName);void climb();void play();//對基類play的覆蓋(在原有的基礎上進行覆蓋)
};
class Dog :public Pet 
{
public:Dog(std::string theName);void bark();void play();//對基類play的覆蓋
};
Pet::Pet(std::string theName)
{name = theName;
}
void Pet::eat()
{std::cout<<name<<"正在吃東西"<<std::endl;
}
void Pet::sleep()
{std::cout << name << "正在睡覺" << std::endl;
}
void Pet::play()
{std::cout << name << "正在玩耍" << std::endl;
}
Cat::Cat(std::string theName):Pet(theName)//Cat的構造器繼承Pet的構造器
{
}
void Cat::climb()
{std::cout << name << "正在爬樹" << std::endl;
}
void Cat::play()
{Pet::play();std::cout << name << "正在玩球" << std::endl;
}
Dog::Dog(std::string theName):Pet(theName)//Cat的構造器繼承Pet的構造器
{
}
void Dog::bark()
{std::cout << name << "正在叫" << std::endl;
}
void Dog::play()
{Pet::play();std::cout << name << "正在追趕那只豬" << std::endl;
}
int main()
{//第一種方法:創建對象//Cat cat("加菲貓");//這個Cat類實例化一個對象cat,取名叫做“加菲貓”。//Dog dog("小灰灰");//cat.eat();//使用指針的話就要用到->操作,而不能使用結構的.操作(點操作)。//cat.sleep();//cat.play();//先調用基類play()函數,再調用子類的play()函數//cat.climb();//此種創建對象方式可以使用Dog子類對象dog//dog.eat();//dog.sleep();//dog.play();//先調用基類play()函數,再調用子類的play()函數//dog.bark();//此種創建對象方式可以使用//第二種方法:指針方式創建對象//定義一個指針變量的形式來對它進行初始化Pet *cat = new Cat("加菲貓");//運行的時候才調用new,分配的是Cat類型的指針,給了cat,(為什么它可以用Pet來接受呢?因為Cat繼承于Pet,所以使用Pet接受是沒有問題的)Pet *dog = new Dog("小灰灰");//同上//Cat子類對象catcat->eat();//使用指針的話就要用到->操作,而不能使用結構的.操作(點操作)。cat->sleep();cat->play();//此種方法創建對象:只調用基類play()函數,不再調用子類的play()函數//cat->climb();//此種Pet *cat = new Cat("加菲貓");創建對象方式:不能調用子類的該方法(但是我們明明在Cat子類里對play方法進行了覆蓋)//Dog子類對象dogcat->eat();cat->sleep();cat->play();//此種方法創建對象:只調用基類play()函數,不再調用子類的play()函數。((但是我們明明在Dog子類里對play方法進行了覆蓋,但實際上調用的是基類的play方法Pet::play()而不是兩個覆蓋的子類中的play()方法))//cat->bark();//此種Pet *dog = new Dog("小灰灰");創建對象方式:不能調用子類的該函數delete cat;delete dog;return 0;
}

該最佳點就是速度最優內存最節省的最佳點。

因為cat和dog都是Pet類型的指針,肯定會調用Pet類型的方法,這樣子優化之后執行起來的速度才是最快的。

??

虛方法的版本:(只需要在基類里邊的play()函數前邊加上virtual關鍵字)

#include<string>
#include<iostream>class Pet
{
public:Pet(std::string theName);//構造函數void eat();void sleep();virtual void play();//前邊加上關鍵字virtual變成虛函數
protected:std::string name;
};
class Cat :public Pet
{
public:Cat(std::string theName);void climb();void play();//對基類play的覆蓋(在原有的基礎上進行覆蓋)
};
class Dog :public Pet 
{
public:Dog(std::string theName);void bark();void play();//對基類play的覆蓋
};
Pet::Pet(std::string theName)
{name = theName;
}
void Pet::eat()
{std::cout<<name<<"正在吃東西"<<std::endl;
}
void Pet::sleep()
{std::cout << name << "正在睡覺" << std::endl;
}
void Pet::play()
{std::cout << name << "正在玩耍" << std::endl;
}
Cat::Cat(std::string theName):Pet(theName)//Cat的構造器繼承Pet的構造器
{
}
void Cat::climb()
{std::cout << name << "正在爬樹" << std::endl;
}
void Cat::play()
{Pet::play();std::cout << name << "正在玩球" << std::endl;
}
Dog::Dog(std::string theName):Pet(theName)//Cat的構造器繼承Pet的構造器
{
}
void Dog::bark()
{std::cout << name << "正在叫" << std::endl;
}
void Dog::play()
{Pet::play();std::cout << name << "正在追趕那只豬" << std::endl;
}
int main()
{//第一種方法:創建對象//Cat cat("加菲貓");//這個Cat類實例化一個對象cat,取名叫做“加菲貓”。//Dog dog("小灰灰");//cat.eat();//使用指針的話就要用到->操作,而不能使用結構的.操作(點操作)。//cat.sleep();//cat.play();//先調用基類play()函數,再調用子類的play()函數//cat.climb();//此種創建對象方式可以使用Dog子類對象dog//dog.eat();//dog.sleep();//dog.play();//先調用基類play()函數,再調用子類的play()函數//dog.bark();//此種創建對象方式可以使用//第二種方法:指針方式創建對象//定義一個指針變量的形式來對它進行初始化Pet *cat = new Cat("加菲貓");Pet *dog = new Dog("小灰灰");//Cat *cat = new Cat("加菲貓");//Dog *dog = new Dog("小灰灰");//Cat子類對象catcat->eat();//使用指針的話就要用到->操作,而不能使用結構的.操作(點操作)。cat->sleep();cat->play();//此種方法Pet *cat = new Cat("加菲貓");創建對象再加上基類虛函數的方法:先調用基類play()函數,再調用子類的play()函數cat->climb();//這種Cat *cat = new Cat("加菲貓");創建對象方式:可以調用子類的該方法(但是我們明明在Cat子類里對play方法進行了覆蓋)//Dog子類對象dogdog->eat();dog->sleep();dog->play();//此種方法創建對象Pet *dog = new Dog("小灰灰");再加上基類虛函數的方法:先調用基類play()函數,再調用子類的play()函數dog->bark();//這種Dog *dog = new Dog("小灰灰");創建對象方式:可以調用子類的該函數((但是我們明明在Dog子類里對play方法進行了覆蓋,但實際上調用的是基類的play方法Pet::play()而不是兩個覆蓋的子類中的play()方法))delete cat;delete dog;return 0;
}

Tips:

??

------抽象方法------

它實際上像一個接口(接口就類似于像C中的printf()函數輸出到桌面上,因為我們只需要根據這個函數所要求的參數提示把他寫進去他就可以實現輸出了,但是它內部是如何調用顯卡等的我們不用管,所以printf可以認為是一個接口);那么什么時候要實現它呢?當我們的子類繼承到它的時候,然后我們需要運用到這個接口的時候,才對他進行具體的實現。

因為下邊會有不同的動物,玩法也不同,所以在基類里邊就不需要對這個方法進行具體的實現。

因為在這個類里邊他是沒有實現的,它是一個抽象的方法,沒有實現的只有在繼承的時候才來實現它。

class Pet
{
public:Pet(std::string theName);//構造函數virtual void eat();//虛函數virtual void sleep();//虛函數virtual void play()=0;//定義為抽象的方法。下邊不用對它進行實現
protected:std::string name;
};
class Cat :public Pet
{
public:Cat(std::string theName);void climb();void play();//對基類play的覆蓋(在原有的基礎上進行覆蓋)
};
class Dog :public Pet 
{
public:Dog(std::string theName);void bark();void play();//對基類play的覆蓋
};
Pet::Pet(std::string theName)
{name = theName;
}
void Pet::eat()
{std::cout<<name<<"正在吃東西"<<std::endl;
}
void Pet::sleep()
{std::cout << name << "正在睡覺" << std::endl;
}
//void Pet::play()
//{
//	std::cout << name << "正在玩耍" << std::endl;
//}//因為它是一個抽象的方法所以這里不用給他寫實現的東西
Cat::Cat(std::string theName):Pet(theName)//Cat的構造器繼承Pet的構造器
{
}
void Cat::climb()
{std::cout << name << "正在爬樹" << std::endl;
}
void Cat::play()
{Pet::play();std::cout << name << "正在玩球" << std::endl;
}
Dog::Dog(std::string theName):Pet(theName)//Cat的構造器繼承Pet的構造器
{
}
void Dog::bark()
{std::cout << name << "正在叫" << std::endl;
}
void Dog::play()
{Pet::play();std::cout << name << "正在追趕那只豬" << std::endl;
}
//下邊主函數同上

PS總結:抽象方法就是在基類里邊不用對它進行寫實現的方法,就是虛方法=0即可;

--------多態-------

class ClxBase
{public:ClxBase(){}virtual ~ClxBase(){}virtual void dosomething()//虛函數,為了方便下邊的覆蓋調用{std::cout<<"Do something in class ClxBase"<<std::endl;}};
class ClxDerived:public ClxBase
{public:ClxDerived(){}~ClxDerived(){std::cout<<"Output from the destructor of class ClxDerived"<<std::endl}void dosomething(){std::cout<<"Do something in class ClxDerived"<<std::endl;}};
int main()
{ClxBase *pTest=new ClxDerived;//進行一個聲明和定義(這里new出來的是一個ClxDerived對象,給了pTest,)(事實上這個對象就是指向子類的)pTest->dosomething();//然后pTest指向dosomethingdelete pTest;return 0;
}

析構器都是虛方法。

#include<string>
#include<iostream>class ClxBase
{
public:ClxBase(){}//virtual ~ClxBase()//{//}//帶virtual的析構函數,下邊輸出結構會調用子類的析構函數如左下圖~ClxBase(){}//不帶virtual的析構函數,下邊輸出結構不會調用子類的析構函數如右下圖(后邊ClxDerived子類的析構函數根本就沒有被執行到)virtual void dosomething()//虛函數,為了方便下邊的覆蓋調用{std::cout << "Do something in class ClxBase" << std::endl;}};
class ClxDerived :public ClxBase
{
public:ClxDerived(){}~ClxDerived(){std::cout << "執行了子類的析構函數" << std::endl;}void dosomething(){std::cout << "Do something in class ClxDerived" << std::endl;}};
int main()
{ClxBase *pTest = new ClxDerived;//進行一個聲明和定義(這里new出來的是一個ClxDerived對象,給了pTest,)(事實上這個對象就是指向子類的)pTest->dosomething();//然后pTest指向dosomething//(如果基類的析構不帶virtual的話,意思就是它調用了這個子類,但是沒有對這個子類進行析構,這是非常非常危險的)delete pTest;return 0;
}

結果展示:

??

//(如果基類的析構不帶virtual的話,意思就是它調用了這個子類,但是沒有對這個子類進行析構,這是非常非常危險的)

1內存泄漏就是內存申請了沒有進行釋放。2虛方法的作用就是使得我們的編譯器變聰明.

如果我們根本就不必要在基類里邊對它寫實現我們就把他寫成抽象函數也就是純虛函數=0就行了,(為什么說基類才用寫虛函數,因為虛函數所繼承的函數他自動也會變成虛函數的,所以我們只用在基類里邊寫就行了)

?

總結

以上是生活随笔為你收集整理的C++:随笔6---new\delete\虚方法\抽象方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。