最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++類型轉(zhuǎn)換、IO流與特殊類的設(shè)計(jì)方法實(shí)例

 更新時(shí)間:2025年12月13日 14:09:44   作者:停云?  
在現(xiàn)代編程中,C++作為一種強(qiáng)大的面向?qū)ο缶幊陶Z(yǔ)言,其靈活性和高效性在開發(fā)中得到了廣泛應(yīng)用,類型轉(zhuǎn)換和輸入輸出流(IO流)是C++語(yǔ)言的兩個(gè)重要組成部分,這篇文章主要介紹了C++類型轉(zhuǎn)換、IO流與特殊類的設(shè)計(jì)方法的相關(guān)資料,需要的朋友可以參考下

一、類型轉(zhuǎn)換

1、內(nèi)置類型與內(nèi)置類型之間轉(zhuǎn)換

(1)隱式類型轉(zhuǎn)換

整形、浮點(diǎn)數(shù)、字符之間可互相隱式類型轉(zhuǎn)換

int i = 3.14;   // double ->  int
int i1 = 'A';   // char   ->  int
double d = 10;  // int    ->  double
char c = 97;    // int    ->  char

(2)顯式類型轉(zhuǎn)換(也叫強(qiáng)制轉(zhuǎn)換)

指針與整形,指針與指針之間可以強(qiáng)制類型轉(zhuǎn)換

// int* pi = 100;       // err, int不可隱式轉(zhuǎn)換為int*
int* pi = (int*)100;    // int可強(qiáng)轉(zhuǎn)為int*

// char* pc = pi;       // err, int*不可隱式轉(zhuǎn)換為char*
char* pc = (char*)pi;   // int*可強(qiáng)轉(zhuǎn)為char*

2、自定義類型與內(nèi)置類型之間的轉(zhuǎn)換

(1)內(nèi)置類型→\to→自定義類型

通過構(gòu)造函數(shù),內(nèi)置類型可以隱式轉(zhuǎn)換為自定義類型

class A
{
    int _a;
public:
    A(int a)
        :_a(a)
    {}
};

void test02()
{
    string s = "xxxxx"; // const char* -> string
    A a = 20;  // int -> A
}

(2)自定義類型→\to→內(nèi)置類型

通過operator 內(nèi)置類型,自定義類型可以轉(zhuǎn)換為內(nèi)置類型

class A
{
    int _a;
public:
    A(int a)
        :_a(a)
    {}
    
    // 將A類對(duì)象轉(zhuǎn)為int類型。不需要寫返回值
    operator int()
    {
        return 10 * _a;
    }
    
    // 將A類對(duì)象轉(zhuǎn)為bool類型
    operator bool()
    {
        if(_a % 2 == 0) 
            return true;
        else
        	return false;
    }
};
void test03()
{
    A a(9);
    int i = a;          // 等價(jià)于 int i = a.operator int();
    cout << i << endl;  // 輸出 90
    bool t = a;         // 等價(jià)于 bool t = a.operator bool();
    cout << t << endl;  // 輸出 0
}

比較典型的應(yīng)用就是在OJ刷題中,可能會(huì)遇到輸入數(shù)據(jù)個(gè)數(shù)未知的情況
C語(yǔ)言寫法:

int t; //t是你要輸入的數(shù)據(jù)
while (scanf("%d", &t) != EOF) 
{
    //...
}

C++寫法:

int t; //t是你要輸入的數(shù)據(jù)
while (cin >> t)
{
    //...
}

C++寫法本質(zhì)上依賴下面兩個(gè)函數(shù)

cin >> t返回值仍然是istream對(duì)象,istream類型的對(duì)象可以轉(zhuǎn)化為bool類型

(3)自定義類型→\to→自定義類型

也是通過構(gòu)造函數(shù)支持

class A
{
    int _a;
public:
    A(int a)
        :_a(a)
    {}

    int get() { return _a; }
};

class B
{
    int _b;
public:
    B(int b)
        :_b(b)
    {}
    
    // 提供了A類對(duì)象的構(gòu)造
    B(A a)
        :_b(a.get())
    {}
};

void test04()
{
    A a(999);
    B b = a;    // A類型 -> B類型
}

3、C++新增的類型轉(zhuǎn)換(了解即可)

C++祖師爺覺得C語(yǔ)言的類型轉(zhuǎn)換不夠規(guī)范,于是就引入了下面四種類型轉(zhuǎn)換操作符

(1)static_cast

static_cast對(duì)應(yīng)隱式類型轉(zhuǎn)換

double d = 3.14;
int i = static_cast<int>(d);    
// 相當(dāng)于 int i = d;

(2)reinterpret_cast

reinterpret_cast對(duì)應(yīng)強(qiáng)制類型轉(zhuǎn)換

int i = 10;
char* p = reinterpret_cast<char*>(&i);  
// 相當(dāng)于 char* p = (char*)&i;

(3)const_cast

const_cast最常用的用途就是刪除變量的const屬性

void test05()
{
    int a = 10;
    const int* p1 = &a;
    int* p2 = const_cast<int*>(p1);  // const int* 轉(zhuǎn) int*
    // 等價(jià)于 int* p2 = (int*)p1;
    
    *p2 = 20;
    cout << a << endl;      // 20
    cout << *p1 << endl;    // 20
    cout << *p2 << endl;    // 20
}

注意不要像下面那樣去掉const屬性

void test05()
{
    const int a = 10;
    int* p = (int*)&a;  // a被const修飾,這里卻用非const指針接收
    *p = 999;

    cout << a << endl;
    cout << *p << endl;

    printf("%p\n", &a);
    printf("%p\n", p);
}

運(yùn)行結(jié)果

這個(gè)結(jié)果很是意外,p存儲(chǔ)的就是a的地址,但*p的結(jié)果卻與a不同!這與編譯器優(yōu)化有關(guān),實(shí)踐中不要寫這樣的代碼。

(4)dynamic_cast

dynamic_cast用于多態(tài)類型的向下轉(zhuǎn)換(運(yùn)行時(shí)檢查)

向上轉(zhuǎn)換:子類指針/引用 →\to 父類指針/引用(賦值兼容規(guī)則)

向下轉(zhuǎn)換:父類指針/引用 →\to 子類指針/引用(用dynamic_cast更安全)

注:dynamic_cast只能用于父類含有虛函數(shù)的類

class A
{
public :
    int _a;	// 為了方便觀察,設(shè)為共有
    A(int a)
        :_a(a)
    {}

    virtual void f(){}	
};

class B : public A 
{
public:
    int _b;	// 為了方便觀察,設(shè)為共有
    B(int b)
        :A(999)
        ,_b(b)
    {}
};

void func_ptr(A* p)
{
    // 若p指向是B類對(duì)象(或者B的子類),則可以轉(zhuǎn)換;否則轉(zhuǎn)換失敗,返回nullptr
    B* pb = dynamic_cast<B*>(p);    // A* 轉(zhuǎn) B*
    if(pb)
        cout << pb->_a << ' ' << pb->_b << endl;
    else 
        cout << "轉(zhuǎn)換失敗" << endl;
}

void func_ref(A& r)
{
    try{
        // 若r引用的是B類對(duì)象(或者B的子類),則可以轉(zhuǎn)換;否則轉(zhuǎn)換失敗,拋異常std::bad_cast
        B& rb = dynamic_cast<B&>(r);		// A& 轉(zhuǎn) B&
        cout << rb._a << ' ' << rb._b << endl;
    }
    catch(const std::bad_cast& e)
    {
        cout << "catch(const std::bad_cast& e)" << endl;
    }
}

void test06()
{
    A a(10);
    B b(20);
    
    func_ptr(&a);
    func_ptr(&b);

    func_ref(a);
    func_ref(b);
}

運(yùn)行結(jié)果

二、IO流

這里只介紹一些常用的

1、C++標(biāo)準(zhǔn)IO流

用法

1.流插入、流提取

cout << t: 把變量t里的內(nèi)容寫入到終端
cin >> t:  從終端讀取數(shù)據(jù),并將其放到變量t。注意: 該過程會(huì)自動(dòng)忽略掉空白字符!

2.getput

int get(); 從終端讀取單個(gè)字符,返回其ASCII碼值
istream& get (char& c); 從終端讀取單個(gè)字符并把其放到c中,返回cin(istream只有一個(gè)對(duì)象cin)
// get()函數(shù)不會(huì)忽略掉空白字符!

ostream& put (char c);	把字符c寫入到終端

舉例

void test()
{
    char c;
    c = cin.get();     // 輸入ab, 然后按回車
    cout << c << endl;
    cin.get(c);
    cout << c << endl;

    cout.put('x');  
}

運(yùn)行結(jié)果

效率

為了兼容C語(yǔ)言的IO流,cincout的效率會(huì)略低于printfscanf(只有輸入/輸出數(shù)據(jù)量達(dá)到 106 及以上時(shí),才會(huì)有明顯差距)
打比賽時(shí),如果你只想用cincout,可以加上下面代碼關(guān)閉流同步從而提高cincout的效率

ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// 加上上面代碼后,就不能將C++的IO與 C的IO混用(例如一會(huì)用cout,一會(huì)用printf)

2、C++文件IO流

ofstream

ofstream用于把內(nèi)容寫入到文件。

示例:

#include<fstream>   // 文件操作要包含這個(gè)頭文件
void test01()
{
    ofstream fout("test.txt");	
    // 創(chuàng)建一個(gè)ofstream對(duì)象fout,并將其連接到文件test.txt
    // 若test.txt不存在,則會(huì)新建該文件;若test.txt存在,則會(huì)清空其內(nèi)容
    
    fout << "abcdef";	// 把a(bǔ)bcdef寫入到test.txt
    fout << "你好!";	// 把你好!寫入到test.txt
    // fout的用法與cout類似。(因?yàn)閛fstream繼承了ostream)
    // fout析構(gòu)時(shí)會(huì)自動(dòng)關(guān)閉文件。
}

運(yùn)行后查看test.txt文件

如果想在原文件末尾追加內(nèi)容,需加上ios::app

// test.txt內(nèi)容:abcdef你好!
ofstream fout("test.txt", ios::app); // ios::app表示在文件末尾追加內(nèi)容
fout << "xxxx";

運(yùn)行后查看文件

ifstream

ifstream用于從文件中讀取數(shù)據(jù)

示例1

void test02()
{
    // test.txt的內(nèi)容:abcdef你好!
    ifstream fin("test.txt");   
    // 創(chuàng)建一個(gè)ifstream對(duì)象fin,并將其連接到文件test.txt
    
    string s;
    fin >> s;       // 從test.txt中讀取數(shù)據(jù)并放入到s
    cout << s;
    // fin的用法與cin類似。(因?yàn)閕fstream繼承了istream)
    // fin析構(gòu)時(shí)會(huì)自動(dòng)關(guān)閉文件。
}

運(yùn)行結(jié)果

示例2

void test02()
{
    ifstream fin("m.cpp");   // 創(chuàng)建一個(gè)ifstream對(duì)象fin,并將其連接到文件m.cpp
    
    // is_open返回值:成功打開返回true,否則返回false。
    if(!fin.is_open())  // 也可這樣寫:if(!fin),因?yàn)橛衞perator bool函數(shù)
    {
        cout << "打開失敗" << endl;
        return;
    }

    // 把m.cpp的代碼全部打印到終端
    char c;
    while(fin.get(c)) // 不要用 fin >> c, 會(huì)忽略掉空白字符
        cout << c; 
        
	// 或者寫成下面那樣,與上面等價(jià),效率更高
	// cout << fin.rdbuf(); 
}

運(yùn)行結(jié)果

文本讀寫與二進(jìn)制讀寫

(1)文本讀寫

上述介紹的文件操作都是對(duì)文本進(jìn)行操作,該操作其實(shí)會(huì)把數(shù)據(jù)轉(zhuǎn)換為字符流。

ofstream fout("test.txt");
int t = 123456;
fout << t;

tint類型,占四個(gè)字節(jié),值為123456,在內(nèi)存中的存儲(chǔ)方式是00000000 00000001 11100010 01000000
fout << t是把t寫入到test.txt文件,難道是把00000000 00000001 11100010 01000000寫進(jìn)去嗎?
答:并非如此,而是先把整數(shù)123456轉(zhuǎn)換為字符串"123456",然后再寫入到test.txt。
(你想一想,二進(jìn)制文件全是0101...多難讀懂啊,轉(zhuǎn)化為字符流不就好多了)

// test.txt內(nèi)容:123456
ifstream fin("test.txt");
int t;
fin >> t;

test.txt文件的內(nèi)容都是字符,實(shí)際存儲(chǔ)的內(nèi)容是字符串123456。
fin >> t是先把字符串"123456"轉(zhuǎn)為整數(shù)123456,再放到變量t

(2)二進(jìn)制讀寫文件

文本讀寫會(huì)把數(shù)據(jù)轉(zhuǎn)化為字符流,而二進(jìn)制讀寫不會(huì)。

  • 二進(jìn)制讀寫:數(shù)據(jù)在內(nèi)存中怎么存,就怎么寫。
  • 二進(jìn)制讀寫需要用到以下兩個(gè)函數(shù):
ostream& write (const char* s, streamsize n);	
// 把地址從s開始、共有n個(gè)字節(jié)的數(shù)據(jù)寫入到文件

istream& read (char* s, streamsize n);
// 從文件中讀取n個(gè)字節(jié)的數(shù)據(jù),放到地址為s的位置

示例

struct Date
{
    int year;
    int month;
    int day;
};

void test03()
{
    ofstream fout("test.txt", ios::binary);  // ios::binary 表示以二進(jìn)制模式
    Date d = { 2025,12,12 };
    fout.write((const char*)&d, sizeof(d)); // 把d以二進(jìn)制形式寫到test.txt
    fout.close();   // 關(guān)閉文件,防止與下面的fin沖突

    Date d1;
    ifstream fin("test.txt", ios::binary);
    fin.read((char*)&d1, sizeof(d1));       // 把test.txt內(nèi)容讀取到d1
    cout << d1.year << ' ' << d1.month << ' ' << d1.day;    // 輸出:2025 12 12
}

打開test.txt,發(fā)現(xiàn)是亂碼。因?yàn)橛浭卤緹o法識(shí)別二進(jìn)制文件

圖片、音頻、游戲存檔等文件是以二進(jìn)制方式存儲(chǔ)的,此時(shí)就需要用二進(jìn)制讀寫文件。
現(xiàn)在我有一張圖片,路徑是C:\E\Furina.jpg,我想把它拷貝到當(dāng)前寫代碼的文件下

void test03()
{
	// 注意:\是轉(zhuǎn)義字符,\\ 表示單個(gè)斜杠
    ifstream fin("C:\\E\\Furina.jpg", ios::binary);
    ofstream fout("fufu.jpg", ios::binary);
    char c;
    while(fin.get(c))	// 本質(zhì)是逐字節(jié)讀取數(shù)據(jù)
        fout.put(c);
        
    // 也可以這樣寫,效率更快:
    // fout << fin.rdbuf();
}

運(yùn)行一下,就成功把照片復(fù)制過來了

三、特殊類的設(shè)計(jì)

1、不能被拷貝的類

將其拷貝構(gòu)造與賦值重載用delete修飾即可

class A
{
    // ... 
public:
	// 加上delete
    A(const A&) = delete;
    A& operator=(const A& ) = delete;
    // ...
};

例如庫(kù)里面的cin、cout對(duì)象就不能被拷貝

2、不能被繼承的類

加上final即可

class A  final
{
    // ....
};

3、只能在堆上創(chuàng)建對(duì)象的類

學(xué)習(xí)下面兩部分前,需回顧一下前置知識(shí)

#include<iostream>
using namespace std;

class A
{
private:
    int _val = 888;
    void func()
    {
        cout << "void func()" << endl;
    }
    
public:
    static void test()
    {
        A a;
        cout << a._val << endl;	// 這里可以訪問私有成員變量嗎?
        a.func();		// 這里可以訪問私有成員函數(shù)嗎?
    }
};

int main()
{
    A::test();
    return 0;
}

運(yùn)行結(jié)果

你可以這樣理解:類中的靜態(tài)成員函數(shù)是該類的友元。

回過頭再來設(shè)計(jì)只能在堆上創(chuàng)建對(duì)象的類:

將構(gòu)造函數(shù)設(shè)為私有,然后禁用拷貝構(gòu)造與賦值重載。再提供靜態(tài)create函數(shù)用于返回堆上的對(duì)象指針

class HeapOnly
{
	// ... 省略成員變量
	
private:
    HeapOnly()
    {
        // ...
    };
    
public:
    static HeapOnly* create()
    {
        return new HeapOnly; 
        // 構(gòu)造函數(shù)是private,而new會(huì)調(diào)用其構(gòu)造函數(shù),這里不會(huì)報(bào)錯(cuò)嗎?
        // 答:不會(huì),你可以理解為create函數(shù)是HeapOnly類的友元
    }
    HeapOnly(const HeapOnly&) = delete;
    HeapOnly& operator=(const HeapOnly&) = delete;
};

void test()
{
    HeapOnly* h1 = HeapOnly::create();
}

4、只能實(shí)例化一個(gè)對(duì)象的類

將構(gòu)造函數(shù)設(shè)為私有,然后禁用拷貝構(gòu)造與賦值重載。再提供靜態(tài)getObj函數(shù)用于返回單一對(duì)象

class SingleObj
{
	// ... 省略成員變量
	
private:
    SingleObj()
    {
        // ...
    };
    
public:
    SingleObj(const SingleObj&) = delete;
    SingleObj& operator=(const SingleObj&) = delete;

    static SingleObj& getObj()
    {
        static SingleObj obj;   // 局部的靜態(tài),第一次運(yùn)行到這里才會(huì)被初始化
        return obj;
    }

    void func()
    {
        cout << "void func()" << endl;
    }
};

void test()
{
    SingleObj& s = SingleObj::getObj();
    s.func();
}

總結(jié) 

到此這篇關(guān)于C++類型轉(zhuǎn)換、IO流與特殊類的設(shè)計(jì)的文章就介紹到這了,更多相關(guān)C++類型轉(zhuǎn)換、IO流與特殊類設(shè)計(jì)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • VC隨機(jī)函數(shù)srand和rand用法

    VC隨機(jī)函數(shù)srand和rand用法

    VC中隨機(jī)函數(shù)最常用就是srand和rand(實(shí)際上是屬于標(biāo)準(zhǔn)C函數(shù)),其中srand負(fù)責(zé)設(shè)置隨機(jī)種子,rand則負(fù)責(zé)生成隨機(jī)數(shù)。使用此二隨機(jī)函數(shù)需要包含<stdlib.h>頭文件
    2016-11-11
  • C++中標(biāo)準(zhǔn)線程庫(kù)的基本使用介紹

    C++中標(biāo)準(zhǔn)線程庫(kù)的基本使用介紹

    大家好,本篇文章主要講的是C++中標(biāo)準(zhǔn)線程庫(kù)的基本使用介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • Qt創(chuàng)建并顯示柱狀圖的方法

    Qt創(chuàng)建并顯示柱狀圖的方法

    Qt Charts 模塊提供了一套易于使用的圖表組件,本文主要介紹了Qt創(chuàng)建并顯示柱狀圖,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • C語(yǔ)言超詳細(xì)講解順序表的各種操作

    C語(yǔ)言超詳細(xì)講解順序表的各種操作

    大家好,今天給大家?guī)淼氖琼樞虮?,我覺得順序表還是有比較難理解的地方的,于是我就把這一塊的內(nèi)容全部整理到了一起,希望能夠給剛剛進(jìn)行學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)的人帶來一些幫助,或者是已經(jīng)學(xué)過這塊的朋友們帶來更深的理解,我們現(xiàn)在就開始吧
    2022-05-05
  • C語(yǔ)言中進(jìn)制知識(shí)匯總

    C語(yǔ)言中進(jìn)制知識(shí)匯總

    在C語(yǔ)言里,整數(shù)有三種表示形式:十進(jìn)制,八進(jìn)制,十六進(jìn)制。 其中以數(shù)字0開頭,由0~7組成的數(shù)是八進(jìn)制。以0X或0x開頭,由0~9,A~F或a~f 組成是十六進(jìn)制。除表示正負(fù)的符號(hào)外,以1~9開頭,由0~9組成是十進(jìn)制。
    2016-05-05
  • C++如何保存bmp圖片

    C++如何保存bmp圖片

    這篇文章主要介紹了C++如何保存bmp圖片問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 解析鴻蒙輕內(nèi)核靜態(tài)內(nèi)存的使用

    解析鴻蒙輕內(nèi)核靜態(tài)內(nèi)存的使用

    摘要:靜態(tài)內(nèi)存實(shí)質(zhì)上是一個(gè)靜態(tài)數(shù)組,靜態(tài)內(nèi)存池內(nèi)的塊大小在初始化時(shí)設(shè)定,初始化后塊大小不可變更。靜態(tài)內(nèi)存池由一個(gè)控制塊和若干相同大小的內(nèi)存塊構(gòu)成??刂茐K位于內(nèi)存池頭部,用于內(nèi)存塊管理。內(nèi)存塊的申請(qǐng)和釋放以塊大小為粒度
    2021-06-06
  • Vscode自定義注釋模板的實(shí)現(xiàn)示例

    Vscode自定義注釋模板的實(shí)現(xiàn)示例

    本文主要介紹了Vscode自定義注釋模板的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Linux下C語(yǔ)言的fork()子進(jìn)程函數(shù)用法及相關(guān)問題解析

    Linux下C語(yǔ)言的fork()子進(jìn)程函數(shù)用法及相關(guān)問題解析

    fork()函數(shù)在Linux下可以用于產(chǎn)生一個(gè)子進(jìn)程,這里我們挑選了兩個(gè)fork相關(guān)的面試題,來看一下Linux下C語(yǔ)言的fork()子進(jìn)程函數(shù)用法及相關(guān)問題解析
    2016-06-06
  • C++中string字符串分割函數(shù)split()的4種實(shí)現(xiàn)方法

    C++中string字符串分割函數(shù)split()的4種實(shí)現(xiàn)方法

    最近筆試經(jīng)常遇到需要對(duì)字符串進(jìn)行快速分割的情景,下面這篇文章主要給大家介紹了關(guān)于C++中string字符串分割函數(shù)split()的4種實(shí)現(xiàn)方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06

最新評(píng)論

乾安县| 扶余县| 花垣县| 历史| 甘孜| 霞浦县| 鄂温| 永定县| 施甸县| 安陆市| 昌江| 永丰县| 定结县| 塘沽区| 池州市| 鄂州市| 石渠县| 靖边县| 克拉玛依市| 洪洞县| 常山县| 广饶县| 莱阳市| 漳平市| 都昌县| 孟津县| 高唐县| 黄山市| 邳州市| 河曲县| 翼城县| 富蕴县| 延安市| 温宿县| 茂名市| 招远市| 五原县| 怀柔区| 师宗县| 乳源| 易门县|