override,final的使用,两者都是针对虚函数,也就是说要有virtual关键字
1.override,final的使用,兩者都是針對虛函數,也就是說要有virtual關鍵字
#include <iostream>
?
//C++中的final和override主要是針對虛函數
//加了final表示拒絕重寫,這是為了使某些情況下,拒絕接口的重寫
//override,聲明重寫父類的方法,前提是要有virtual關鍵字修飾函數。
//當父類沒有接口,會提示錯誤
class ye
{
public:
??? //final修飾的函數必須是虛函數,通過這種方式避免重寫了一些老的接口
??? virtual void print() final //加了final表示虛函數無法重寫了
??? {
??????? std::cout << "爺爺\n";
??? }
??? virtual void run()
??? {
??????? std::cout << "爺爺run\n";
??? }
};
?
class ba :public ye
{
public:
??? void run() override
??? {
??????? std::cout << "爸爸run\n";
??? }
};
?
void main()
{
??? ba ba1;
??? ba1.run();? //結果是:爸爸run
?
??? std::cin.get();
}
2.RTTI 實時類類型檢測
#include <iostream>
//rtti,實時類類型檢測
//typeid,dynamic_cat必須依賴于虛函數表
//類型不匹配轉換失敗,返回為空,類型安全
?
//成員變量的覆蓋
//虛函數有虛函數表確定數據類型
?
class A
{
public:
??? int num;
??? static int data;
??? virtual void run()
??? {
??????? std::cout << "A run \n";
??? }
};
?
//對A中的靜態變量進行初始化
int A::data = 1;
class B :public A
{
public:
??? int num = 0;
??? static int data;
??? void run()
??? {
??????? std::cout << "B run\n";
??? }
??? void test()
??? {
??????? std::cout << num << "\n";
??????? std::cout << "B test\n";
??? }
};
?
int B::data = 2;
?
void main()
{
??? A a1;
??? B b1;
??? A *p1 = &a1;
??? A *p2 = &b1;
??? B *p3(nullptr);
??? //p3 = static_cast<B *>(p1);//直接賦地址,不安全,與虛函數無關
??? p3 = reinterpret_cast<B *>(p2);
??? std::cout << p3 << "\n";
??? p3->test();
?
??? std::cin.get();
??? //此次運行結果:
??? //008FFE70
??? //0
??? //B test
}
3.C函數指針復習
#include <stdlib.h>
?
int add(int a,int b)
{
??? return a + b;
}
?
void run()
{
??? printf("\nrun");
}
?
void main()
{
??? int(*p)(int, int) = add;//指向add的函數指針
??? void(*p1)() = run;//指向run的函數指針
??? printf("%d\n",p(1,2));
??? printf("%d\n",(*p)(1,2)); //*p編譯器自動將*p解釋為p
??? printf("%d\n",(******p)(1,2));//*p編譯器自動將*p解釋為p
?
??? printf("%d\n", (&(**p))(1, 2)); //&沒有*不可以執行,超過兩個地址就不可以
??? //&p不能,
??? //printf("%d\n", (&(p))(1, 2));
??? printf("%p,%p,%p", &p, *p, p);
??? printf("\n%p,%p,%p", &p1, *p1, p1);
??? //取地址,就是CPU即將調用函數執行
?
??? getchar();
}
運行結果:
4.CPP函數指針
#include <iostream>
#include <stdlib.h>
?
void add(int a,int b)
{
??? std::cout << a + b << std::endl;
}
?
void main()
{
??? void(*p)(int, int) = add;
??? p(1, 2);
??? (*p)(1,2); //函數指針,會被當做指針來處理,*p與p效果一樣
??? (*************p)(1,2);//函數指針,會被當做指針來處理,*p與p效果一樣
??? (*&p)(1,2);
??? (*******&p)(1,2);
??? std::cout << (void *)p << "? " << (void *)(*p) << std::endl;
??? std::cout << typeid(p).name() << std::endl;
??? std::cout << typeid(*p).name() << std::endl;
??? std::cout << typeid(&p).name() << std::endl;
??? std::cout << typeid(*&p).name() << std::endl;
??? //C++編譯器會自動將*p處理為p
??? std::cin.get();
}
運行結果:
5.類成員函數指針數組
#include <iostream>
#include <stdio.h>
?
//類成員函數指針,類成員函數指針數組,類成員二級函數指針
class com
{
private:
??? int a;
??? int b;
public:
??? com(int x, int y) :a(x), b(y)
??? {
??? }
??? int? jia(int a, int b)
??? {
??????? return a + b;
??? }
??? int? jian(int a, int b)
??? {
??????? return a - b;
??? }
??? int? cheng(int a, int b)
??? {
??????? return a * b;
??? }
??? int? chu(int a, int b)
??? {
??????? return a / b;
??? }
};
?
void main()
{
??? com com1(100, 20);
??? auto fun1 = &com::jia;
??? int(com::*p)(int, int) = &com::jia;? //注意這里要加上對象名
??? std::cout << (com1.*p)(10, 20) << std::endl;//引用對象,類成員函數指針
??? std::cout << typeid(p).name() << std::endl;
??? std::cout << typeid(fun1).name() << std::endl;
?
??? std::cin.get();
}
5.CPP函數指針數組
#include <iostream>
#include <stdio.h>
?
//類成員函數指針,類成員函數指針數組,類成員二級函數指針
class com
{
private:
??? int a;
??? int b;
public:
??? com(int x, int y) :a(x), b(y)
??? {
??? }
??? int? jia(int a, int b)
??? {
??????? return a + b;
??? }
??? int? jian(int a, int b)
??? {
??????? return a - b;
??? }
??? int? cheng(int a, int b)
??? {
??????? return a * b;
??? }
??? int? chu(int a, int b)
??? {
??????? return a / b;
??? }
};
?
typedef int(com::*P)(int, int);//為函數指針定義別名p
void main()
{
??? com com1(100, 200);
??? //下面這種方式也是沒有錯的
??? //P fun1[4] = { &com::jia, &com::jian, &com::cheng,&com::chu };
??? //類成員函數指針數組
??? int(com::*fun1[4])(int, int) = { &com::jia, &com::jian, &com::cheng, &com::chu };
??? for (int i = 0; i < 4; i++)
??? {
??????? std::cout << (com1.*fun1[i])(10, 20) << std::endl;
??? }
??? int(com::**funp)(int, int) = fun1;//指向類成員函數指針的指針
??? for (; funp < fun1 + 4;funp++)
??? {
??????? std::cout << (com1.**funp)(10, 20) << std::endl;
??????? printf("%p",*funp);
??? }
?
??? for (int i = 0; i < 4;i++)
??? {
??????? auto func = fun1[i];
??????? std::cout << typeid(func).name() << std::endl;
??????? printf("%p", func);
??? }
??? std::cin.get();
}
運行結果:
6.高級new對象
#include<iostream>
?
class myclass
{
public:
??? myclass()
??? {
??????? std::cout << "創建\n";
??? }
??? ~myclass()
??? {
??????? std::cout << "銷毀\n";
??? }
};
?
void main()
{
??? char *pcathe = new char[1024];
??? char *pcatheend = pcathe + 1024;
??? std::cout << (void*)pcathe << "?? " << (void*)pcatheend << std::endl;
?
??? myclass *p = new(pcathe)myclass[10];//限定區域分配內存,覆蓋模式
??? std::cout << p << std::endl;
?
??? //delete[] p;一般不需要delete.自動覆蓋
??? std::cout << p << std::endl;
?
??? p = new(pcathe)myclass[10];
??? std::cout << p << std::endl;
?
??? //delete[] p;//只能釋放一次
??? std::cout << p << std::endl;
?
??? /*
??? myclass *pclass = new? myclass[10];
??? std::cout << pclass <<std::endl;
??? delete []pclass;
??? pclass = NULL;
??? std::cout << pclass <<std::endl;
??? pclass = new?myclass[10];
??? std::cout << pclass <<std::endl;
??? delete [] pclass;
??? std::cout << pclass <<std::endl;
??? */
?
??? std::cin.get();
}
總結
以上是生活随笔為你收集整理的override,final的使用,两者都是针对虚函数,也就是说要有virtual关键字的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大蒜辣是怎么回事?
- 下一篇: 通过移位的方式实现相加算法