導航:首頁 > 源碼編譯 > 成員函數的編譯

成員函數的編譯

發布時間:2022-05-21 05:19:15

A. c++問題。關於調用類的對象成員的成員函數

你的problem不是靜態的不能通過類名調用,只能創建b類通過對象調用,而且a類的void
test()須是公有的.
#include
using
namespace
std;
class
A
{
public
:
void
test(){
cout<<"test
A";
}
static
void
stest(){
cout<<"static
test
A";
}
};
class
B
{
public:
void
test(){
a.test();
}
public
:
A
a;
static
A
sa;
};
int
main()
{
B
b;
b.test();
b.a.test();
B::sa.stest();
}
以上三種方法都正確,希望對你有用.

B. 關於一個java中成員函數的代碼,無法編譯,求解決答案,哪裡出錯。

你放置 p1.jisuan(); 的地方,是類初始化的區域,請把放到一個方法當中,或者把Person p1=new Person();
p1.jisuan();
放入static 代碼化

C. 如果不將average函數定義為靜態成員函數行不行程序能否編譯需要做什麼修改為什麼要用靜態成員函數

為什麼要用靜態成員函數?

從上述修改中可以看出,不使用靜態成員函數顯然也能實現相同的功能,那麼,為什麼要使用靜態成員函數呢?

如果把average函數定義為非靜態成員函數,那麼主函數中將出現stud[1](當然,換成stud[0]或者stud[2]也可以),stud[1]的出現破壞了主函數中語句的邏輯性。他人在閱讀主函數時看到stud[1]也許會有疑問:這里為什麼要用stud[1]的成員函數,有什麼特殊含義嗎?是不是this指針必須在指向stud[1]的時候才能求得正確的平均值?降低了主函數的可讀性。

靜態成員函數主要是用來處理靜態數據成員的,而靜態數據成員不只屬於某一個對象,它是為「全部同類對象」所共用的。因此,定義靜態成員函數的目的在於處理「全部同類對象」的共同問題。

靜態成員函數不屬於某一個特定的對象,因為把一個處理「全部同類對象」共同問題的函數定義為某個對象所有是不合邏輯的。靜態成員函數直接使用類名和域運算符調用,提高了語句的邏輯性和可讀性。

樓上認為,使用靜態成員函數的原因在於,不論有沒有定義對象,靜態成員函數都可以直接被調用。這的確是靜態成員函數的一個特點,但是把它作為使用靜態成員函數的原因未免有些牽強。試想,在沒有定義對象的情況下,調用靜態成員函數又有什麼意義呢?

也許有人會說,在沒有定義對象的情況下,靜態成員函數還可以對靜態數據成員進行操作啊。是的,的確可以,可是靜態數據成員又是為誰而設的呢?沒有定義對象,數據成員也變的沒有意義了。

綜上,靜態成員函數的使用,提高了語句的邏輯性和可讀性。

D. 類的有成員函數的聲明但是沒有實現為什麼可以編譯

可以編譯,但鏈接會出錯,因為這不是編譯要檢查的問題

E. 請問什麼是成員函數的定義

成員函數相當於C或C++中的函數。你應該用如下的方式說明一個成員函數:
Type name (Parameter)
//function body
注意:每一個成員函數必須返回一個值或聲明返回為空(void)。它返回類型的說明告訴編譯器它將返回什麼類型的值。在某些情況下,成員函數需要表示它是否成功的完成了它的工作,此時返回類型通常為布爾型的。參數表是用逗號分開的一組變數,它將為成員函數提供所需信息。
下面例子中定義了一個成員函數。通過它,你的矩形類可以計算自己的面積了:

int getArea(int w,int h)
{
int a;
a=w*h;
return a;
}

另外,矩形還需要對自己進行描繪,因此它需要成員函數drawRect(),此時,你的矩形類的定義將如下所示:

public class DrwRect
{
public static void main(String args[])
{
class Rectangle
{
int width,height,area;
public Rectangle(int w,int h)
{
width=w;
height=h;
area=getArea(w,h);
}

protected int getArea(int w,int h)
{
int a;
a=w*h;
return a;
}

public void drawRect()
{
int i,j;
for(i=width;i>0;i--)
System.out.print("#");
System.out.print("") ;

for(i=height-2;i>0;i--)
System.out.print("#");

for(j=width-2;i>0;j--)
System.out.print("");

System.out.print("#");

for(i=width;i>0;i--)
System.out.print("#");

System.out.print("");
}
} //Rectangle

int w=Integer.valueOf(args[0]).intValue();
int h=Integer.valueOf(args[1]).intValue();
Rectangle myrect=new Rectangle(w,h);
myrect.drawRect();
}
}

上例中最後一個「#」號後面還有一個System.out.print("")這是由於這個成員函數在上一行沒有結束而且緩沖區沒有溢出時將不把輸出結果寫屏。若你使用print成員函數,卻沒有得到輸出,這時仔細確認一下你是否以""來結束你的輸出流。

2:不同類型的成員函數
在上例的成員函數聲明中你需要注意兩點:getArea()定義為private型,drawRect()定義為public型。public型意味著任何類都可以調用它。private型,它只能被所聲明的類內部調用。這些說明類型同樣適用於數據變數。
若有人想改變一個私有變數,通常要引用下面的成員函數:

public void setWidth(int w)
{
width=w;
}

注意:在Java中,protected只是作為關鍵字出現,而沒有相應的功能。

3:成員函數的重載
假如你必須在不同情況下發送不同的信息給同一個成員函數的話,該怎麼辦呢?你可以通過對此成員函數說明多個版本(version)的方法來實現重載。重載的本質是創建了一個新的成員函數:你只需給它一個不同的參數列表(parameterlist),如下例所示:

void get Area(int w,int h);
void get Area(float w,float h);

在第二種情況下,成員函數get Area()接受兩個浮點變數作為它的參數,編譯器根據調用時的不同參數來決定該調用哪一種成員函數,假如你把兩個整數提供給成員函數,你就調用第一個成員函數;假如你把兩個浮點數提供給成員函數,第二個成員函數就被調用。

4:靜態成員
除了public、private和protected以外,你還可以把成員說明為static(靜態)。static修飾符表明一個變數或成員函數對所有類的實例都是相同的,你也許想使用一個所有Rectangle類都可以使用的變數,來說明該類的版本(version),假如你把它說明成一個static,那麼該變數將對該類的所有實例都是一樣的,如:

static int version=1;

靜態成員函數和靜態變數的優點就在於他們能在沒有創建類的任何一個實例的情況下被引用,引用時在「.」域前,可直接使用類名而無須使用對象名。例如,drawRect成員函數使用了System.out.println成員函數,但實際上你卻未曾創建一個某個System類的對象,這正是因為out是System類的一個靜態變數,所以你可以直接使用這個成員函數而無須定義一個System對象。

5:構造和析構成員函數
類有一個特殊的成員函數叫做構造成員函數,它通常用於初始化類的數據成員。在創建對象時,會自動調用類的構造成員函數。Java中的構造成員函數必須與該類具有相同的名字,另外,構造成員函數一般都應用public類型來說明,這樣才能在程序任意的位置創建類的實例--對象。
下面是一個Rectangle類的構造成員函數,它帶有兩個參數,分別表示矩形的長和寬:
public Rectangle(int w,int h)
{
width=w;
height=h;
area=getArea(w,h);
}

除了構造成員函數以外,類還提供了析構成員函數,當對象被從內存中刪除時,該成員函數將會被自動調用。通常,在析構成員函數內,你可以填寫用來回收對象內部的動態空間的代碼。

F. 關於c++中類成員函數問題

1. 在eat()函數中,使用了形如const void eat()的方式,這個在const的用法中叫做:用const 修飾函數的返回值。這種方法的好處,只有在返回值為指針時,才可以顯現出來,就是說:函數返回值(即指針)的內容不能被修改,該返回值只能被賦給加const 修飾的同類型指針。下面是我寫的一段示常式序:
#include <iostream>
using namespace std;

int s=0;

const int *sum(int x,int y)
{
s=x+y;
return &s;
}

int main()
{
const int *p=NULL;//這里的指針p必須為const類型,否則編譯錯誤
p=sum(1,2);
cout<<*p<<endl;

return 0;
}
2. 在sleep()函數中,使用了形如void sleep()const的方式,這個在const的用法中叫做:const 成員函數。這種方法要求:我們應該把不會修改數據成員(即函數中的變數)的函數聲明為const 類型。好處是:如果在編寫const 成員函數時,不慎修改了數據成員,或者調用了其它非const 成員函數,編譯器將指出錯誤,這就會提高程序的健壯性。下面是示常式序:
class Stack
{
public:
void Push(int elem);
int Pop(void);
int GetCount(void) const; // const 成員函數
private:
int m_num;
int m_data[100];
};
int Stack::GetCount(void) const
{
++ m_num; // 編譯錯誤,企圖修改數據成員m_num
Pop(); // 編譯錯誤,企圖調用非const 函數
return m_num;
}
下面是關於Const函數的幾點規則:
1. const對象只能訪問const成員函數,而非const對象可以訪問任意的成員函數,包括const成員函數.
2. const對象的成員是不可修改的,然而const對象通過指針維護的對象卻是可以修改的.
3. const成員函數不可以修改對象的數據,不管對象是否具有const性質.它在編譯時,以是否修改成員數據為依據,進行檢查.
4. 然而加上mutable修飾符的數據成員,對於任何情況下通過任何手段都可修改,自然此時的const成員函數是可以修改它的.

G. C++中類成員函數未實現,是否能夠編譯鏈接通過

如果該成員函數沒有被調用,那麼就不會對編譯連接產生影響,可以通過編譯。

H. c++類成員函數在類外定義,編譯錯誤!!!!!(3個文件)

你的分離編譯錯誤,主要是因為你在main中include linkqueue.h,而link queue的實現放在了cpp中導致。這里你的main include的linkqueeu.cpp,所以不會導致問題。


模板的實現一般都需要放在頭文件中,因為模板類似宏,編譯器需要根據提供的模板參數生成代碼,而如果編譯器看到模板的實現,那麼就生成不了代碼,最後鏈接會出錯。放在cpp里一般是你需要顯式實例化模板,並且不想讓用戶隨意對模板進行實例化,也就是用戶只能使用你提供的特化。

//foo.h
template<typenameT>
structfoo{
voidf();
};

//foo.cpp
#include"foo.h"
template<typenameT>
voidfoo<T>::f(){...}
//
templateclassfoo<int>;//只允許用戶使用int參數


一般不去includecpp文件,當然也不是完全不可以,因為只是一個文件而已。
你將linkqueue.cpp改成linkqueue.hpp或者linkqueue_impl.h等頭文件命名,之後在linkqueue.h中include這個頭文件,在main.cpp中只需要includelinkqueue.h即可。


頭文件一般需要用#ifndef #endif包裹起來,否在可能會出現被多次include的問題,導致編譯錯誤。

#ifndeffile_h
#definefile_h
//類定義,函數聲明等
#endif

I. 什麼叫成員函數有什麼作用

什麼是友元(friend)?
允許另一個類或函數訪問你的類的東西。

友元可以是函數或者是其他的類。類授予它的友元特別的訪問權。通常同一個開發者會出於技術和非技術的原因,控制類的友元和成員函數(否則當你想更新你的類時,還要徵得其它部分的擁有者的同意)。

分清成員函數,非成員函數和友元函數

成員函數和非成員函數最大的區別在於成員函數可以是虛擬的而非成員函數不行。所以,如果有個函數必須進行動態綁定(見條款38),就要採用虛擬函數,而虛擬函數必定是某個類的成員函數。關於這一點就這么簡單。如果函數不必是虛擬的,情況就稍微復雜一點。

看下面表示有理數的一個類:

class rational {
public:
rational(int numerator = 0, int denominator = 1);
int numerator() const;
int denominator() const;

private:
...
};

這是一個沒有一點用處的類。(用條款18的術語來說,介面的確最小,但遠不夠完整。)所以,要對它增加加,減,乘等算術操作支持,但是,該用成員函數還是非成員函數,或者,非成員的友元函數來實現呢?

當拿不定主意的時候,用面向對象的方法來考慮!有理數的乘法是和rational類相聯系的,所以,寫一個成員函數把這個操作包到類中。

class rational {
public:

...

const rational operator*(const rational& rhs) const;
};

(如果你不明白為什麼這個函數以這種方式聲明——返回一個const值而取一個const的引用作為它的參數——參考條款21-23。)

現在可以很容易地對有理數進行乘法操作:

rational oneeighth(1, 8);
rational onehalf(1, 2);

rational result = onehalf * oneeighth; // 運行良好

result = result * oneeighth; // 運行良好

但不要滿足,還要支持混合類型操作,比如,rational要能和int相乘。但當寫下下面的代碼時,只有一半工作:

result = onehalf * 2; // 運行良好

result = 2 * onehalf; // 出錯!

這是一個不好的苗頭。記得嗎?乘法要滿足交換律。

如果用下面的等價函數形式重寫上面的兩個例子,問題的原因就很明顯了:

result = onehalf.operator*(2); // 運行良好

result = 2.operator*(onehalf); // 出錯!

對象onehalf是一個包含operator*函數的類的實例,所以編譯器調用了那個函數。而整數2沒有相應的類,所以沒有operator*成員函數。編譯器還會去搜索一個可以象下面這樣調用的非成員的operator*函數(即,在某個可見的名字空間里的operator*函數或全局的operator*函數):

result = operator*(2, onehalf); // 錯誤!

但沒有這樣一個參數為int和rational的非成員operator*函數,所以搜索失敗。

再看看那個成功的調用。它的第二參數是整數2,然而rational::operator*期望的參數卻是rational對象。怎麼回事?為什麼2在一個地方可以工作而另一個地方不行?

秘密在於隱式類型轉換。編譯器知道傳的值是int而函數需要的是rational,但它也同時知道調用rational的構造函數將int轉換成一個合適的rational,所以才有上面成功的調用(見條款m19)。換句話說,編譯器處理這個調用時的情形類似下面這樣:

const rational temp(2); // 從2產生一個臨時
// rational對象

result = onehalf * temp; // 同onehalf.operator*(temp);

當然,只有所涉及的構造函數沒有聲明為explicit的情況下才會這樣,因為explicit構造函數不能用於隱式轉換,這正是explicit的含義。如果rational象下面這樣定義:

class rational {
public:
explicit rational(int numerator = 0, // 此構造函數為
int denominator = 1); // explicit
...

const rational operator*(const rational& rhs) const;

...

};

那麼,下面的語句都不能通過編譯:

result = onehalf * 2; // 錯誤!
result = 2 * onehalf; // 錯誤!

這不會為混合運算提供支持,但至少兩條語句的行為一致了。

然而,我們剛才研究的這個類是要設計成可以允許固定類型到rational的隱式轉換的——這就是為什麼rational的構造函數沒有聲明為explicit的原因。這樣,編譯器將執行必要的隱式轉換使上面result的第一個賦值語句通過編譯。實際上,如果需要的話,編譯器會對每個函數的每個參數執行這種隱式類型轉換。但它只對函數參數表中列出的參數進行轉換,決不會對成員函數所在的對象(即,成員函數中的*this指針所對應的對象)進行轉換。這就是為什麼這個語句可以工作:

result = onehalf.operator*(2); // converts int -> rational

而這個語句不行:

result = 2.operator*(onehalf); // 不會轉換
// int -> rational

第一種情形操作的是列在函數聲明中的一個參數,而第二種情形不是。

盡管如此,你可能還是想支持混合型的算術操作,而實現的方法現在應該清楚了:使operator*成為一個非成員函數,從而允許編譯器對所有的參數執行隱式類型轉換:

class rational {

... // contains no operator*

};

// 在全局或某一名字空間聲明,
// 參見條款m20了解為什麼要這么做
const rational operator*(const rational& lhs,
const rational& rhs)
{
return rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}

rational onefourth(1, 4);
rational result;

result = onefourth * 2; // 工作良好
result = 2 * onefourth; // 萬歲, 它也工作了!

這當然是一個完美的結局,但還有一個擔心:operator*應該成為rational類的友元嗎?

這種情況下,答案是不必要。因為operator*可以完全通過類的公有(public)介面來實現。上面的代碼就是這么做的。只要能避免使用友元函數就要避免,因為,和現實生活中差不多,友元(朋友)帶來的麻煩往往比它(他/她)對你的幫助多。

然而,很多情況下,不是成員的函數從概念上說也可能是類介面的一部分,它們需要訪問類的非公有成員的情況也不少。

讓我們回頭再來看看本書那個主要的例子,string類。如果想重載operator>>和operator<<來讀寫string對象,你會很快發現它們不能是成員函數。如果是成員函數的話,調用它們時就必須把string對象放在它們的左邊:

// 一個不正確地將operator>>和
// operator<<作為成員函數的類
class string {
public:
string(const char *value);

...

istream& operator>>(istream& input);
ostream& operator<<(ostream& output);

private:
char *data;
};

string s;

s >> cin; // 合法, 但
// 有違常規

s << cout; // 同上

這會把別人弄糊塗。所以這些函數不能是成員函數。注意這種情況和前面的不同。這里的目標是自然的調用語法,前面關心的是隱式類型轉換。

所以,如果來設計這些函數,就象這樣:

istream& operator>>(istream& input, string& string)
{
delete [] string.data;

read from input into some memory, and make string.data
point to it

return input;
}

ostream& operator<<(ostream& output,
const string& string)
{
return output << string.data;
}

注意上面兩個函數都要訪問string類的data成員,而這個成員是私有(private)的。但我們已經知道,這個函數一定要是非成員函數。這樣,就別無選擇了:需要訪問非公有成員的非成員函數只能是類的友元函數。

本條款得出的結論如下。假設f是想正確聲明的函數,c是和它相關的類:

·虛函數必須是成員函數。如果f必須是虛函數,就讓它成為c的成員函數。

·operator>>和operator<<決不能是成員函數。如果f是operator>>或operator<<,讓f成為非成員函數。如果f還需要訪問c的非公有成員,讓f成為c的友元函數。

·只有非成員函數對最左邊的參數進行類型轉換。如果f需要對最左邊的參數進行類型轉換,讓f成為非成員函數。如果f還需要訪問c的非公有成員,讓f成為c的友元函數。

·其它情況下都聲明為成員函數。如果以上情況都不是,讓f成為c的成員函數。
回答者:Dyemn - 高級經理 六級 12-27 08:29

友元函數要在一個類體內說明,形式為:
friend 類型名 友元函數名(形參表);
然後在類體外對友元函數進行定義,定義的格式和普通函數相同,但可以通過對象作為參數直接訪問對象的私有成員
友元函數說明如下:
1)必須在類的說明中說明友元函數,說明時以關鍵字friend開頭,後跟友元函數的函數原型,友元函數的說明可以出現在類的任何地方,包括在private和public部分;
2)注意友元函數不是類的成員函數,所以友元函數的實現和普通函數一樣,在實現時不用"::"指示屬於哪個類,只有成員函數才使用"::"作用域符號;
3)友元函數不能直接訪問類的成員,只能訪問對象成員,
4)友元函數可以訪問對象的私有成員,但普通函數不行;
5)調用友元函數時,在實際參數中需要指出要訪問的對象,

J. 一個C++頭文件與成員函數編譯為目標文件封裝的問題

除了頭文件以外的文件只要文件裡面聲明定義都能找的到就可以編譯成單獨的目標文件(事實上很多編譯器也正是這樣做的),編譯之後確實可以這樣子使用,但是經過編譯之後很多函數的代碼都會出席那改變,那時候就不知道你打算怎麼用了

閱讀全文

與成員函數的編譯相關的資料

熱點內容
汽車小壓縮機拆解 瀏覽:825
雲桌面卡是因為伺服器的原因嗎 瀏覽:377
qd123壓縮機 瀏覽:969
pn532讀取加密門禁卡 瀏覽:85
win10文件夾屬性里無法加密 瀏覽:34
比特幣加密的條件 瀏覽:848
求購現成影視app源碼 瀏覽:572
wdsecurity加密版 瀏覽:813
雲伺服器和雲豐雲 瀏覽:188
伺服器如何設置獨立ip 瀏覽:857
tar命令打包文件夾 瀏覽:1000
刪除linux用戶和組 瀏覽:548
小米的程序員都用什麼筆記本 瀏覽:703
位元組三面演算法題 瀏覽:971
伺服器保護有什麼好處 瀏覽:894
全部下載完後進行統一解壓 瀏覽:393
遠嫁的程序員媽媽 瀏覽:555
1024程序員節安全攻防挑戰賽 瀏覽:786
怎麼解除txt加密 瀏覽:772
javahttp流 瀏覽:656