CGoods.h
#pragma once
#include <iostream>
using namespace std;
/*
class與struct的區別:
在C++中class和struct
class Node{
默認是私有的(private)
};
class Node{
默認是公有的(public)
};
struct 在C和C++中的區別:
在C++中struct定義以後 struct Node{}; 直接可以Node node
在C中struct定義以後 struct Node{}; 必須struct Node node (struct 必須加)
*/
class CGoods
{
public:
CGoods() //默認構造函數
{ //體內實現 -》內聯函數
cout << this << endl;
cout << "CGoods()" << endl;
_pname = new char(1);
_pname = '\0';
_amount = 0;
_price = 0.0;
}
CGoods(const char *name, int amount, double price); //重載默認構造函數
CGoods(CGoods const &src); //重載拷貝構造函數
void operator = (CGoods const &src); //重載賦值運算符函數
void show();
~CGoods(); //默認析構函數 析構函數不帶參數所以不能進行重載
private:
char *_pname;
int _amount;
double _price;
};
CGood.cpp
#include "CGoods.h"
#include <string>
#include <iostream>
using namespace std;
/*
類外實現函數和類體實現函數的區別:
類體內實現函數自動被編譯器處理成inline(內聯)函數
內聯函數:編譯器對一些特殊函數進行內聯擴展(取代函數的調用節省函數調用帶來的額外時間開支)
用於消除調用函數時所造成的固有的時間消耗方法
內聯函數(由帶參宏(Macros)在源碼級實現)與宏的差別:
宏不執行類型的檢查(只是簡單的文本替換),正常參數也不進行檢查,而內聯函數要進行檢查
內聯函數可以隨意使其內聯或者不內聯
通常,編譯器比程序設計者更清楚對於一個特定的函數是否合適進行內聯擴展
內聯函數使用可能大大增加編譯時間
*/
#if 0 //在類體內實現
CGoods::CGoods()
{
cout << this << endl;
cout << "CGoods()" << endl;
_pname = new char(1);
_pname = '\0';
_amount = 0;
_price = 0.0;
}
#endif
/*
const 的用法: 允許程序員告訴編譯器某值是保持不變的
const int num = 10; //const data num不能被修改
num = 12; (錯誤)
const 修飾指針
const char *name 與 char * const name 區別:
const int num = 10;
const int tmp = 10;
const int * a = #
a = &tmp;
*a = tmp; (錯誤)
const位於*的左側表示指針所指針的數據是一個常量不能被修改,而指針的本身是一個變量,可以指向其他的內存單元
int num = 10;
int tmp = 10;
int * const b = #
b = &tmp; (錯誤)
*b = 20;
const位於*的右側表示指針所指針的數據是一個變量可以被修改,指針本身是一個常量,不能被修改指向其他的內存單元(可以通過解引用進行修改)
cosnt int num = 10;
int * const b = # (錯誤)
const int * const b = #(可以)
const 常量不能賦值給 const 保護的指針
const修飾成員函數:
(1)const修飾的成員函數不能修改任何的成員變量(mutable修飾的變量除外)
(2)const成員函數不能調用非const成員函數,因爲非const成員函數可以會修改成員變量
*/
CGoods::CGoods(const char *name, int amount, double price)
{
cout << this << endl;
cout << "CGoods(char *name, int amount, double price)" << endl;
/*
strlen 和 sizeof的區別:
strlen:字符串的長度,以"\0"爲字符結束標誌
sizeof:分配的數組所佔用的實際內存空間內的大小
*/
cout << "sizeof(name) :"<< sizeof(name) << endl;
cout << "strlen(name) :" << strlen(name) << endl;
_pname = new char[strlen(name) + 1];
//strcpy(_pname, name); //vs準備棄用strcpy 需要在有文件中加#pragma warning(disable:4996)使用
memcpy(_pname, name, strlen(name) + 1); //void *memcpy(void *dest, const void *src, size_t n); 內存拷貝函數
_amount = amount;
_price = price;
}
CGoods::CGoods(const CGoods &src)
{
cout << "src: " << &src << "->" << "this: " << this << endl;
cout << "CGoods(CGoods const &src)" << endl;
_pname = new char[strlen(src._pname) + 1];
//strcpy(_pname, src._pname);
memcpy(_pname, src._pname, strlen(src._pname) + 1);
_amount = src._amount;
_price = src._price;
}
void CGoods::operator = (const CGoods &src)
{
if (this == &src) {
return;
}
cout << "src:" << &src << "->" << "this:" << this << endl;
cout << "operator = (CGoods const &src)" << endl;
delete[] _pname;
_pname = NULL;
_pname = new char[strlen(src._pname) + 1];
//strcpy(_pname, src._pname);
memcpy(_pname, src._pname, strlen(src._pname) + 1);
_amount = src._amount;
_price = src._price;
}
void CGoods::show() {
cout << "name: " << _pname << endl;
cout << "amount:" << _amount << endl;
cout << "price:" << _price << endl;
}
CGoods::~CGoods()
{
cout << "~CGoods()" << endl;
delete[] _pname;
_pname = NULL;
}
oop.c
#include "CGoods.h"
int main() {
/*
成員函數可以被看作類作用域外的全局函數,不在對象分配的空間裏
只有虛函數纔會在類對象裏有一個指針,存放虛函數的相關地址信息
*/
cout << "sizeof(CGoods):" << sizeof(CGoods) << endl;
CGoods good1;
cout << "sizeof(good1):" << sizeof(good1) << endl;
//調用不帶參數的構造函數
cout << "===================================good1" << endl;
CGoods good2("shangpin2", 10, 12.5); //調用帶參數的構造函數
cout << "sizeof(good2):" << sizeof(good2) << endl;
cout << "===================================good2" << endl;
/*拷貝構造函數
**當對象產生除內存以外的內存分配時,可能發生淺拷貝,因此需要自定義拷貝構造函數進行深拷貝
*/
CGoods good3(good2);
cout << "===================================good3" << endl;
/*
對象進行賦值時,發生發生淺拷貝,產生內存泄漏問題
防止對象的自賦值;
釋放當前資源
重新開闢空間
拷貝成員變量
*/
good1 = good2;
cout << "===================================good1 = good2" << endl;
good2 = good2;
cout << "===================================good2 = good2" << endl;
//用臨時對象構建同類型的新對象,此時臨時對象不生成,用構造臨時對象的方式直接構造對象
CGoods good4 = CGoods("shangpin4", 12, 12.6);
cout << "===================================good4 = CGoods(shagnpin4, 12, 22.2);" << endl;
//臨時對象賦值產生臨時對象,當語句結束時釋放臨時對象的資源(臨時對象的生存週期-》臨時對象所在語句),調用析構函數
CGoods good5;
good5 = CGoods("shangpin5", 12, 12.6);
cout << "===================================CGoods(shangpin5, 12, 12.6);" << endl;
good1.show();
good2.show();
good3.show();
good4.show();
cout << "===================================show()" << endl;
good1.~CGoods(); //析構函數可以自己進行調用,構造函數不能自己調用系統自動進行調用
cout << "===================================good1.~CGoods()" << endl;
const int num = 10;
return 0;
}