Wednesday 6 February 2019

C++ Program Design

类class:
class Box
{
   public:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
   
      double getVolume(void)
      {
         return length * breadth * height;
      }
}; // Define function inside of class
double Box::getVolume(void)
{
    return length * breadth * height;
}// Define function outside of class   范围解析运算符::
Box myBox;          // 创建一个对象
 
myBox.getVolume();  // 调用该对象的成员函数
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数,如下所示:
#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;
      void setWidth( double wid );
      double getWidth( void );
 
   private:
      double width;
};
 
// 成员函数定义
double Box::getWidth(void)
{
    return width ;
}
 
void Box::setWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   Box box;
 
   // 不使用成员函数设置长度
   box.length = 10.0; // OK: 因为 length 是公有的
   cout << "Length of box : " << box.length <<endl;
 
   // 不使用成员函数设置宽度
   // box.width = 10.0; // Error: 因为 width 是私有的
   box.setWidth(10.0);  // 使用成员函数设置宽度
   cout << "Width of box : " << box.getWidth() <<endl;
 
   return 0;
}

保护(protected)成员

保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
在下一个章节中,您将学习到派生类和继承的知识。现在您可以看到下面的实例中,我们从父类 Box 派生了一个子类 smallBox
下面的实例与前面的实例类似,在这里 width 成员可被派生类 smallBox 的任何成员函数访问。
#include <iostream>
using namespace std;
 
class Box
{
   protected:
      double width;
};
 
class SmallBox:Box // SmallBox 是派生类
{
   public:
      void setSmallWidth( double wid );
      double getSmallWidth( void );
};
 
// 子类的成员函数
double SmallBox::getSmallWidth(void)
{
    return width ;
}
 
void SmallBox::setSmallWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   SmallBox box;
 
   // 使用成员函数设置宽度
   box.setSmallWidth(5.0);
   cout << "Width of box : "<< box.getSmallWidth() << endl;
 
   return 0;
}

继承中的特点

有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。
  • 1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected, private
  • 2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected, private
  • 3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private, private
但无论哪种继承方式,上面两点都没有改变:
  • 1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
  • 2.protected 成员可以被派生类访问。
int i = 3;
int j = 5;
const int * p= &i;
则:
p = &j; /* 正确,p可以被重新赋值 */
*p = j; /* 错误,因为他改变的是p所指向的变量的值。*/
常量指针与指针常量vi
常量指针表示一个指针指向的变量为常量及带有const属性(e.x. const int *p) , 而指针常量表示一个指针本身为常量及指针本身带有const属性(e.x. int *const p), 常量指针指向的对象由于有const属性, 无法直接改变, 但是指针本身值(及指针指向的内存地址)可以改变, 而指针常量则是指针本身有const属性, 指针的值(及指针指向的内存地址)无法直接改变, 而该地址内的变量可以改变。
例子:
const char *p = “Hello, World”; //表示指针p是一个常量字符串的首地址, 指针p为常量指针
char a[20] = “Hello, World”;
char *const p = a; //表示指针p本身为常量, 它将一直指向该内存区域直到它被释放, 指针p为指针常量。(注意: 此时p的值虽然无法改变, 但是a的值可以改变。)
指针常量一般常用于当一个指针由始至终都指向一个对象时使用。
动态内存分配:
用new运算符实现动态内存分配:
P=new T;
T是任意类型名,P是类型为T*的指针。动态分配出一片大小为sizeof(T)字节的内存空间,并且将该内存空间的起始地址赋值给P。比如:
int *pn;
pn=new int;
*pn =5;
P=new T[N];//N*sizeof(T)
int *pn;
int i = 5;
pn=new int[i*20];
pn[0] = 20;
pn[100] = 30;//error
new T;
new T[n];
这两个表达式返回值的类型都是 T *
用“new”动态分配的内存空间,需要用“delete”运算符进行释放;
int *p = new int;
*p = 5;
delete p;
delete p;//shows error: p only can be deleted for one time
 — — — — — — — — — — — — — — — — — — 
int *p = new int[20];
p[0] = 1;
delete []p;
内联函数:
函数调用是有时间开销的。如果函数本身只有几条语句,执行非常快,而且函数被反复执行很多次,相比之下调用函数所产生的这个开销就会显得比较大。
为了减少函数调用的开销,引入了内联函数机制。编译器处理对内联函数的调用语句时,是将整个函数的代码插入到调用语句处,而不会产生调用函数 的语句。
inline int Max(int a, int b){
if(a>b) return a;
return b;
}
 函数重载:
(1) int Max(double f1, double f2){}
(2) int Max(int n1, int n2){}
(3) int Max(int n1, int n2, int n3){}
Max(3.4,2.5); //1
Max(2,4); //2
Max(1,2,3); //3
Max(3,2.4); //error
函数的缺省参数:
void func(int x1, int x2 = 2, int x3 = 3) {}
func(10); //equal to func(10,2,3)
func(10, 8); //equal to func(10,8,3)
func(10, , 8); //error. Only continuous right side parameters missing
构造函数
class Complex {
private:
 double real, imag;
public:
 Complex(double r, double i = 0);
};
Complex::Complex(double r, double i) {
 real = r; imag = i;
}
Complex c1; //error,缺少构造函数的参数
Complex *pc = new Complex; //error,没有参数
Complex c1(2);//ok
Complex c1(2, 4), c2(3, 5);
Complex *pc = new Complex(3, 4);
 — — — — — — — — — — — — — 
可以有多个构造函数,参数个数或类型不同
class Complex {
private:
 double real, imag;
public:
 void Set(double r, double i);
 Complex(double r, double i);
 Complex(double r);
 Complex(Complex c1, Complex c2);
};
Complex::Complex(double r, double i) {
 real = r; imag = i;
}
Complex::Complex(double r) {
 real = r; imag = 0;
}
Complex::Complex(Complex c1, Complex c2) {
 real = c1.real + c2.real;
 imag = c1.imag + c2.imag;
}
Complex c1(3), c2(1, 0), c3(c1, c2);
// c1 = {3, 0}, c2 = {1, 0}, c3 = {4, 0};
构造函数最好是public的,private构造函数不能直接用来初始化对象
#include <iostream>
using namespace std;
class CSample {
 int x;
public:
 CSample() {
  cout << "Constructor 1 Called" << endl;
 }
 CSample(int n) {
  x = n;
  cout << "Constructor 2 Called" << endl;
 }
};
int main() {
 CSample array1[2];  //Constructor 1 Called    Constructor 1 Called
 cout << "step1" << endl;  //step1
 CSample array2[2] = { 4,5 }; //Constructor 2 Called  Constructor 2 Called
 cout << "step2" << endl; //step2
 CSample array3[2] = { 3 };//Constructor 2 Called  Constructor 1 Called
 cout << "step3" << endl; //step3
 CSample *array4 = new CSample[2]; //Constructor 1 Called    Constructor 1 Called
 delete[]array4;
 return 0;
}
构造函数在数组中的使用:
class Test {
public:
 Test(int n) {}       //1
 Test(int n,int m){}  //2
 Test(){}             //3
};
Test array1[3] = { 1,Test(1,2) }; //1,2,3
Test array2[3] = { Test(2,3),Test(1,2),1 }; //2,2,1
Test *pArray[3] = { new Test(4),new Test(1,2) };//1,2

No comments:

Post a Comment