當前位置:首頁 » 編程軟體 » 編譯器繼承

編譯器繼承

發布時間: 2022-05-31 04:45:57

『壹』 include的作用與繼承一樣么

include的作用與繼承完全不同。

include是插入文本的意思。也就是有一篇文字的東西寫在另一個文件里,告訴編譯器:在include的位置,插入該文件文字內容後再開始編譯。

通常插入的東西是「頭文件」,文件擴展名.h, 但實際上,插入別的也可以,例如xxx.c 也可以。不信,你試試簡單的例子:
現有程序 b.c
寫一個新程序 a.c
a.c 的內容就寫一行:
#include "b.c"
編譯a.c並運行a.exe,所得結果與b.c一樣吧!

繼承,不是文本(文字)的承繼,而是含義的繼承,它是在編譯(翻譯)和鏈接過程中發生的事。例如,你定義了一新類,並聲明它繼承CWin類,這樣一來,所有CWin的成員變數,成員函數都自動變成你的新類的成員變數,成員函數,(如果你重新聲明了某個變或函數,則以重寫的為准)。

『貳』 關於繼承中的構造方法

這句話是對的,不過要加個前提條件.那就是"在子類對象的構造過程中"

這就能很好解釋一樓為什麼說後半句是錯的了,因為一樓沒有創建子類對象,也就是沒有new,當然也就不會涉及構造方法,所以他認為後半句是錯的.實際上,這句話是對的,不過樓主應該加上"在子類對象的構造過程中" 這句話,而且整個這段話(也就是你問的),出現在馬士兵老師講課的視頻中,一字不差,是對的.

另外,如果當用戶沒有定義構造方法時,編譯器會為類自動添加形如類名() { } 的無參構造方法,但是一但自己定義了構造 方法,編譯器將不再自動添加.

也就是說構造方法不是必須有的.如果你之前一直未自定義構造方法,當你new一個對象時,系統會自動調用默認的一個無參構造方法,給你對象的實例變數賦初值,比如int型默認為0.但一旦你自己定義了構造方法並new一個對象後,你再new一個對象時系統將不再為你自動提供默認的無參構造方法,那麼你必須自己定義一個構造方法,否則編譯出錯

『叄』 C++繼承的構造順序

1.構造函數
先看下面的類定義
class
B1 class B2
{ {
public: public:
int
i; int i;
B1() { i = 0;
} B2() { i = 0; }
virtual void f()
{} virtual void f() {}
}
; } ;

class
M1 class M2
{ {
public: public:
int
i; int i;
M1() { i = 0;
} M2() { i = 0; }
virtual void mf()
{} virtual void mf() {}
}
; };

class C : public B1, public B2
{
public:
virtual void f() {}
M1 m1;
M2 m2;
};

(1)編譯器會不會為C生成默認構造(default ctor)
編譯器只在需要時才會為一個類生成def
ctor。「需要時」指:
a.一個類有虛函數
b.一個類有虛基類
c.一個類的基類有def ctor
d.一個類的成員類有def ctor
在這里,class C符合c,d兩個條件,編譯器會為它生成def
ctor.

(2)默認構造的內容
編譯器生成的def ctor是這樣的
C::C()
{
B1::B1()
B2::B2()
設定虛表指針指向C的虛表
m1::M1()
m2::M2()
}
a.按聲明順序構造基類
b.設定虛表指針
c.按聲明順序構造成員類

(3)對自定義構造函數的改造
對於B1,B2,M1,M2,已有構造函數,但編譯器會對其改造,加入一些代碼,完成必要的初始化工作。改造後的ctor如下:(以B1為例)
B1::B1()
{
設定虛表指針指向B1的虛表
i = 0;
}
a.設定虛表指針
b.如果用戶寫有代碼(如i=0),則執行這些代碼

(4)綜合(2),(3),構造函數完整代碼如下
T::T()
{
按聲明順序構造基類
設定虛表指針
按聲明順序構造成員類
如果用戶寫有代碼,則執行這些代碼
}
在用戶代碼執行前,基類與成員類已構造完畢,虛指針已設定。

所以C的構造順序是:B1-〉B2-〉虛指針設定-〉m1-〉m2->C自己的代碼(如果有的話)
由(3)可知,每個類的ctor中,都會暫時將虛指針指向自己的虛表。調用B1::B1時,虛指針指向B1的虛表,然後在C::C中,虛指針被重新設定為C的虛表。
在繼承體系中,構造是由上而下的,B1或B2構造時,C還未構造。C構造時,B1和B2已構造完成。

所以在繼承體系中,一個類的構造函數執行時,該類的所有基類已構造完畢,虛指針已設定,所有成員類也已構造完畢。但該類的所有子類均未構造完成。

2.析構函數
(1)編譯器會不會為C生成析構函數(dtor)
編譯器只在需要時才會為一個類生成dtor。「需要時」指:
a.類的基類有析構
b.類的成員類有析構
與構造不同,少了兩點,因為在一個類析構時,這是一個破壞操作(destory),既然類以已經沒用了,何必再把虛指針設一下呢。

(2)析構的內容
編譯器生成的析構是這樣的
C::~C()
{
m2::M2()
m1::M1()
B2::B2()
B1::B1()
}
a.按聲明順序相反的順序析構成員類
b.按聲明順序相反的順序析構基類
這里的相反順序是C++標准規定的要求,不同編譯器都應做到,否則不符合標准(實際上編譯器或多或少都有不符標準的地方,當然不是指這里所說的順序問題)

(3)完整的析構的調用順序
對於已有析構函數的類,編譯器會對其改造,加入一些代碼,完成必要的工作。改造後的dtor如下:
T::~T()
{
設定虛表指針指向T的虛表
執行用戶代碼
按聲明順序相反的順序析構成員類
按聲明順序相反的順序析構基類
}
這是完整的析構的調用順序
在用戶代碼執行前,虛指針已重新設定,以便用戶代碼能正確執行。然後再析構成員類和基類。

所以,如果上面例子中的五個類都有析構函數的話,調用順序是:
虛指針設定-〉C自己的代碼->m2-〉m1-〉B2-〉B1
每個類的dtor中,都會暫時將虛指針指向自己的虛表。調用C::~C時,虛指針指向C的虛表,然後在B1::~B1中,虛指針被重新設定為B1的虛表。

可見,在繼承體系中,析構是由下而上的,B1或B2析構時,C已被析構。C析構時,B1和B2還未被析構。
所以在繼承體系中,一個類的析構函數執行時,該類的所有基類還未被析構,所有成員類也未被析構。但該類的所有子類均已析構完成。

3.虛函數
在構造或析構中調用虛函數,會怎樣.如:
B1::B1()
{
f();
}
調用的是B1::f()還是C::f()
答案是B1::f()
每個類的ctor中,都會暫時將虛指針指向自己的虛表。調用B1::B1時,虛指針指向B1的虛表
所以是B1::f()
如果在C的構造函數中調用f(),那就調用C::f()

『肆』 java面向對象關於繼承的問題

Base base=new Child();
這個分為兩部分。。Base base這是定義。。base=new Child();這是賦值。。
因為你把base定義為 Base類型。。所以編譯器把他當做Base類型。。至於實際類型。。運行的時候才能確定。。所以不能訪問Child的屬性和方法。。

Child child=new Child();
Base child=new Child();
這個的不同應該明白了撒。。就是你寫代碼的時候。。編譯器把他們看成的類型是不一樣的。。

『伍』 繼承了介面中的方法為什麼編譯器提示是錯誤的

你的介面的setFree和setPay方法漏了參數,而在繼承後重寫時又傳入了double類型的值,當然會編譯不通過。

『陸』 編譯器和編程軟體有什麼區別啊

編譯器就是將編程語言轉化為機器語言的東東。
編程軟體一般包含編譯器。比如VS。

『柒』 初學c++類繼承與派生的問題

簡單地說,編譯器生成代碼的時候,該調用哪個成員函數是根據類型判斷的,b的類型是基類指針,編譯器就調用基類的成員函數fun1。為什麼是這樣呢?

因為繼承關系下,編譯器允許我們把子類當作基類用,這是合理的,也就是向上類型轉換,把子類的信息全部丟棄(只是忽略,內存中還保留著,可以用靜態轉換static_cast轉換回去,也就是向下類型轉換),因此你把a的地址賦給b時,編譯器把a當作基類用,當然應該和沒有子類的情況一樣,所以調用了基類的fun1。那如何才能根據實際的類型而不是先做向上轉換來調用成員函數呢?

c++為了解決你這個問題,引入了多態,也就是虛函數,在成員函數定義前加上virtual。比如:
#include<iostream.h>
class BaseClass
{
public:
virtual void fun1(){cout<<"調用基類的fun1"<<endl;}
};
class DerivedClass:public BaseClass
{
public:
void fun1(){cout<<"調用派生類的fun1"<<endl;}//這里可以不加virtual,因為父類已經聲明了,當然也可以加上,為了代碼可讀性
};
main()
{
DerivedClass a;
BaseClass*b=&a;
b->fun1();
}

為什麼和不加virtual不一樣呢?因為虛函數的入口存在了對象的內存空間,有一張虛函數表,調用的時候是去找表找到入口地址後調用,因此對象的內存是什麼類型就會調用什麼類型的虛函數,即使向上類型轉換了,虛函數表也不會變,照樣調用。

『捌』 C++編程題 關於 繼承和多態 的

首先你的第一個問題,d.vf2();這里涉及到一個c++的原則,子類有父類的同名函數,如果不是虛函數的話,則會「隱藏」父類的函數,不管參數是否一致,都會隱藏!所以你的dd::vf2(int
i)這個函數就把bb::vf2()隱藏了,因此dd就不會繼承這個函數。至於為什麼這么設計,以前貌似看某處b.s的訪談,說為了減小出錯的幾率,以免子類的使用者不小心誤使用了父類的函數。
看起來貌似第二個問題和第一個問題是一樣的,但是結果卻不同,其實你應該去了解下c++的對象模型,你就知道它的運作機理了。
對於虛函數,是動態綁定的,在對象內部有一個虛函數表,表裡面是一個個的函數指針,指向當前對象的各個虛函數真正的代碼,當你代碼執行到調用虛函數那裡的時候,會去這個表裡面查,然後取出函數指針再調用。
如果是非虛函數,則是靜態綁定的,也就是說在編譯的時候就已經確定要調用哪個函數!
不管b::vf2、d::vf2、d::vf3都是非虛函數,都會發生靜態綁定。
也就是說編譯器在編譯代碼的時候就會決定到底調用哪個函數。它怎麼決定呢?看類型。如下:
bp->vf2();
//這句話,編譯器看到了bp是b*類型的,於是就去找b::vf2()這個函數,找到了於是綁定成功。
d.vf2();
//這句話,編譯器看到d是d類型的,於是去找d::vf2()這個函數,由於上面提到的隱藏原則,d不存在這個函數,於是沒找到,出錯。
dp->vf2();
//這句話,編譯器看到dp是d*類型的,去找d::vf2()這個函數,於是同上,找不到,出錯。
dp->vf3();//編譯器看到dp是d*類型的,於是找d::vf3()這個函數,找到了,於是綁定成功。
分析完這四句編譯器的行為,你就明白了吧。
我寫這么多,你好歹多加點分吧……

『玖』 C51是一種專為MCS-51系列單片機設計的高級語言C編譯器,它繼承了符合ANSI標准對嗎

對的吧,雖然說具體概念好像是如此,但最主要的還是動手實踐。我玩過很多次51單片機,編譯器是基於C 語言的keil 4,挺好用的。

『拾』 C++的繼承機制

從語言和概念的角度來說,子類繼承父類是繼承了所有protected和public非static成員(static成員是共享而不是繼承),而成員包括函數和數據。所以從概念上來說,成員函數和成員變數都被繼承了。
從實現上來說,實現要在外顯上不違反概念,在內部可以非常隨意。所有的實現子類繼承父類成員函數只是子類共享了父類的函數,沒有兩份拷貝。編譯器知道父類的某成員函數的地址,那麼在子類調用父類的該方法時,編譯器只要產生
call 函數地址 的代碼就可以調用父類的方法,完全沒有必要保留兩份拷貝。
換句話來說,非虛方法的調用在編譯時就已經確定了,編譯器掌握一切信息。編譯器選擇最高效的實現(只保留一份函數拷貝)來符合C++語言概念。從邏輯上認為子類繼承了父類的方法。

對虛函數,如果是在子類對象上用.操作符調用虛函數,那麼編譯器可以確定函數地址,此時不需要使用虛函數調用機制。只有在基類指針上用->操作符調用虛函數時,才會使用虛函數調用機制。此時編譯器不知道基類指針指向具體什麼類型的對象,所以它不知道到底調用哪個函數,它產生類似如下代碼:
call [vftable + functionoffset]
也就是通過虛函數表中對應函數偏移來調用,虛函數表的布局是編譯器已知的。當具體某個對象構造時,他們初始化虛表使得其中指針都指向自己的虛函數。這樣就通過這個實現來滿足了C++的虛函數概念。

舉個例子:
class base {
private:
int member1;
protected:
int member2;
public:
int fun();
virtual int virtualfun();
};

class derive : public base {
public:
int member;
public:
virtual int virtualfun();
};

在代碼中使用:derive test;
(以微軟c/c++編譯器為例)那麼test在內存中可能是如下布局:
110000 vftable----------->112000
110004 base::member1
110008 base::member2
11000c derive::member
----------------------------
112000 (vftable[0])derive::virtualfun------>410000
----------------------------
410000 int derive::virtualfun(){ ... }
410500 int base::virtualfun(){ ... }
411000 int base::fun(){ ... }

熱點內容
十年前電腦做伺服器 發布:2024-05-21 11:14:35 瀏覽:970
解壓之音 發布:2024-05-21 11:07:37 瀏覽:865
安卓如何玩手機游戲 發布:2024-05-21 10:03:15 瀏覽:109
好的少兒編程學校 發布:2024-05-21 10:02:38 瀏覽:439
c語言字元個數統計 發布:2024-05-21 09:54:31 瀏覽:415
ubuntupython文件 發布:2024-05-21 09:41:01 瀏覽:161
java後端介面 發布:2024-05-21 09:40:59 瀏覽:931
豪華尊貴分別對應哪些配置 發布:2024-05-21 09:40:56 瀏覽:621
逗號幫手體驗密碼是多少 發布:2024-05-21 09:31:44 瀏覽:131
vb資料庫excel 發布:2024-05-21 09:18:57 瀏覽:319