Practice on programming 學習筆記.

class 1

獲得命令行參數

int main(int argc, char *argv[])
{
....

}
argc 代表程序啓動時,命令行參數的個數。C/C++語言規定,可執行程序程序本身的文件名也是一個命令行參數,因此argc的最小值爲1。

char *argv[] 裏存放着指向命令行參數的指針。 copy  file1.txt file2.txt    其中 copy是第一個參數 file1.txt是第二個參數 file2.txt是第三個參數。


class 2

位運算

按位與:通常用來將變量中的某些位清0,且保留其它位不變。也可以用來獲取變量中的某一位。

eg:需要將int型變量的低8位全部置爲0

n=n&0xffffff00;

如果n是short類型的

n&=0xff00;

按位或:按位或通常用來將某些變量的某些位置置一,其它位保持不變。

按位異或:兩個操作數不同置1,相同置0。按位異或運算通常用來將某變量中的某些位取反,其它位保持不變。

eg:將某int變量n的低8位取反

n^=0xff;

異或運算的特點是:若 a^b=c 則 c^b=a以及c^a=b。

這個規律可以用於最簡單的加密解密。

a 原文 b 祕鑰 c 密文

另外異或運算還能實現不需要臨時變量就可以交換兩個變量的值。

int a=7, b=5;
a=a^b;
b=b^a;
a=a^b;

左移運算符<<

表達式 a<<b 的值是將a各二進制位全部左移b位後得到的值,左移時,高位丟棄低位補0。

左移n位相當於乘以2的n次方,比乘法操作快很多。

右移運算符>>

右移時,移出的位丟棄。

對於有符號數,如long 、int 、short、char等類型,右移時符號位將一起移動,且大多數C、C++編譯器規定,符號位爲1高位置1,符號位位0高位補0。

右移你位相當於左操作數除以2的n次方且往小取整。


class 3

內聯函數:將整個函數代碼插入到調用語句處,而不會產生調用函數的語句。

類對象的大小=類所有成員變量的大小之和。

類中缺省爲私有成員。


內聯成員函數:

1)inline關鍵字

2)函數體在類中


class 4

普通成員變量每個對象有各自的一份,而靜態成員變量一共就一份,爲所有對象共享。

sizeof 不會計算靜態成員變量

普通的成員函數必須具體作用於某個對象,而靜態成員函數並不具體作用於某個對象。

靜態成員並不需要通過對象就能訪問。

靜態成員變量本質上是全局變量,哪怕一個對象都不存在,類的靜態成員變量也存在。

靜態成員函數本質上是全局函數。

設置靜態成員這種機制的目的是將與類緊密相關的全局變量和函數寫在類中,看上去像一個整體,便於維護和理解。

必須在定義類的文件中對靜態變量進行一次說明或者初始化。

在靜態成員函數中不能訪問非靜態成員變量也不能掉用非靜態成員函數。


class 5

成員對象和封閉類

成員對象:一個類的成員變量是另一個類的對象。

包含成員對象的類是封閉類。

當封閉類生成時:第一步執行所有成員對象的構造函數,第二步執行封閉類的構造函數。

成員對象構造函數順序與成員對象在類中的說明順序一致,與在成員初始化列表中的順序無關。

當封閉類對象消亡的時候首先執行封閉類的析構函數,然後執行成員對象的析構函數。


class 6

友元 friend

一個類的友元函數可以訪問該類的私有成員。

A是B的友元類,A的成員函數可以訪問B的成員。

友元類的關係,不能繼承,不能傳遞。


class 7

從C++程序到C程序的翻譯

class CCar{
public:
    int price;
    void SetPrice(int p);
};
void CCar::SetPrice(int P){
    price=p;
}
int main()
{
    CCar car;
    car.SetPrice(10000);
    return 0;
}


struct CCar{
    int price;
};
void SetPrice(struct CCar *this, int p)
{
    this->price=p;
}
int main()
{
    struct CCar car;
    SetPrice(&car,10000);
    return 0;
}


this指針作用

指向成員函數所作用的對象。

靜態成員函數中不能使用This指針


class 8 

運算符只能用於基本數據類型

運算符重載:對抽象數據類型也能使用C++原有運算符

運算符重載:對已有運算符賦予多重含義,使同一運算符作用於不同類型的數據時,產生不同的行爲。

賦值運算符只能重載爲成員函數。

成員函數不能滿足使用需求,普通函數又不能訪問類的私有成員,可以重載爲友元函數。

淺複製:執行逐個字節的複製工作。可能會導致內存垃圾,指針回收的時候會產生嚴重的內存錯誤。

深複製:將一個對象指針 變量指向的內容複製到另一個對象中指針成員對象指向的地方。


重載 [ ] 需要注意返回值類型應該是引用類型,否則就不支持 a[i]=elem; 這樣的賦值語句。

前置運算符作爲一元運算符重載,後置運算符作爲二元運算符重載。後置的第二個參數一般爲沒有意義的0.


class 9

用基類指針數組存放指向各種派生類對象的指針,然後遍歷該數組,就能對各派生類對象進行各種操作,是很常用的做法。

example 

Input

3

T 3 4 5

C 9

R 3 4

Out put

CTriangle 5

CRectangle 12

CCycle 254.34

#include <iostream>
#include<stdlib.h>
#include<math.h>
using namespace std;
class CShape
{
public:
	virtual double Area()=0;  //=0意味着虛函數爲純虛函數
	virtual void PrintInfo()=0;
};

class CRectangel:public CShape
{
public:
	int w,h;
	virtual double Area();
	virtual void PrintInfo();
};

class CCycle:public CShape
{
public:
	int r;
	virtual double Area();
	virtual void PrintInfo();
};

class CTriangle:public CShape
{
public:
	int a,b,c;
	virtual double Area();
	virtual void PrintInfo();
};

double CRectangel::Area()
{
	return w*h;
}

void CRectangel::PrintInfo()
{
	cout<<"CRectangle:"<<Area()<<endl;
}

double CCycle::Area()
{
	return 3.14*r*r;
}

void CCycle::PrintInfo()
{
	cout<<"CCyle:"<<Area()<<endl;
}

double CTriangle::Area()
{
	double p=(a+b+c)/2.0;
	return sqrt(p*(p-a)*(p-b)*(p-c));
}

void CTriangle::PrintInfo()
{
	cout<<"CTriangle:"<<Area()<<endl;
}

CShape* pShapes[100];
int myCompare(const void* s1,const void* s2);

int main()
{
	int i,n;
	CRectangel *pr; CCycle *pc; CTriangle *pt;
	cin>>n;
	for(i=0;i<n;i++)
	{
		char c;
		cin>>c;
		switch(c){
		case 'R':
			pr=new CRectangel();
			cin>>pr->w>>pr->h;
			pShapes[i]=pr;
			break;
		case 'C':
			pc=new CCycle();
			cin>>pc->r;
			pShapes[i]=pc;
			break;
		case 'T':
			pt=new CTriangle();
			cin>>pt->a>>pt->b>>pt->c;
			pShapes[i]=pt;
			break;
		}
	}
	qsort(pShapes,n,sizeof(CShape *),myCompare);
	for(i=0;i<n;i++)
		pShapes[i]->PrintInfo();
	return 0;
}

int myCompare(const void* s1,const void* s2)
{
	double a1,a2;
	CShape **p1;
	CShape **p2;
	p1=(CShape**)s1;
	p2=(CShape**)s2;
	a1=(*p1)->Area();
	a2=(*p2)->Area();
	if(a1<a2)
		return -1;
	else if(a2<a1)
		return 1;
	else 
		return 0;
}

在非構造函數,非析構函數的成員函數中調用虛函數,是多態!

多態的關鍵在於通過基類指針或者引用調用一個虛函數時,編譯時不確定調用的是基類的還是派生類的函數,運行時才能確定。----動態聯編


把基類的析構函數聲明爲virtual,通過基類的指針刪除派生類對象時,會首先調用派生類的析構函數然後再調用基類的析構函數。

一個類如果定義了虛函數,最好將類的析構函數也定義爲虛函數。

純虛函數:沒有函數體的虛函數。

抽象類:包含純虛函數的類。

抽象類只能作爲基類使用,不能創建抽象類的對象。

可以定義抽象類的指針和引用。


class 10 

順序文件—一個有限字符構成的順序字符流

使用/創建文件的基本流程   打開文件-》讀寫文件-》關閉文件


寫入文件示例

#include<iostream>
#include<fstream>
#include <cstring>
using namespace std;
class CStudent{
public:
	char szName[20];
	int nScore;
};

int main(){
	CStudent s;
	ofstream OutFile("c:\\tmp\\students.dat",ios::out|ios::binary);
	while(cin>>s.szName>>s.nScore){
		if(stricmp(s.szName,"exit")==0) //名字爲exit結束
			break;
		OutFile.write((char*)&s,sizeof(s));
	}
	OutFile.close();
	return 0;
}

讀出文件示例

#include<iostream>
#include<fstream>
#include <cstring>
using namespace std;
class CStudent{
public:
	char szName[20];
	int nScore;
};

int main(){
	CStudent s;
	ifstream inFile("students.dat",ios::in|ios::binary);
	if(!inFile)
	{
		cout<<"error"<<endl;
		return 0;
	}
	while(inFile.read((char*)&s,sizeof(s))){
		int nReadedBytes=inFile.gcount();
		cout<<s.szName<<""<<s.nScore<<endl;
	}
	inFile.close();
	return 0;
}


class 11

泛型程序設計

Generic Programming

算法實現時不指定具體要操作的數據的類型。

大量編寫模版,使用模版的程序設計。

C++編譯器遵循以下優先順序

1、先找參數完全匹配的普通函數

2、再找參數完全匹配的模版函數

3、在找實參經過自動類型轉換後能匹配的普通函數

4、報錯













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章