【C++侯捷】面向高级对象编程(一)

面向对象高级编程(一)

头文件与类的声明

一些需要注意的点

#include <iostream>
#include "complex.h"

包含的库的文件用<>,包含用户自己建立的文件用"",延伸文件名不一定是.h或.cpp,也有可能是 .hpp或其他或甚至无延伸名。

Header(头文件)中的防卫式声明

例如complex.h

#ifndef __COMPLEX__
#define __COMPLEX__


...

#endif

说明:当第一次引用complex文件时,会定义COMPLEX, 再当以后引入时不会再重复引用下面的

Header(头文件)的布局

#ifndef __COMPLEX__
#define __COMPLEX__

#include <cmath>
class ostream;
class complex;

complex&
 __doapl (complex* this, const complex& r);
--- 前置声明
 
class complex
{
...
};
--- 类声明
complex::function...
--- 类定义

Class的声明

class complex{
public:
	...
	
private:
	...

};

class template(模板)简介

template<typename T>
class complex
{
public:
...

private:
...
T re,im; # T为待定的类型

};

inline(内联)函数

如果函数再class本体中定义,则称之为inline函数。优点是,总的来说,很好、很快。

但是有些函数即使你把他定义为内联函数,编译器也不会把他看成内联函数。

access level(访问级别)

public
private
protect

构造函数

示例

class complex
{
public:
	complex(double r = 0, double i = 0)   //
	: re(r), im(i)                        //
	{}                                    //默认构造函数的实现
	complex& operator += (const complex&);
	double real() const {return re;}
	double imag() const {return im;}
	
private:
	double re, im;
    friend complex& __doapl (complex*, const complex&);
};

对于上述构造函数附参部分,也可以这样写

complex(double r = 0, double i = 0)
{re = r; im = i;}

但是要求按上述写,应该利用构造函数的这个特性。

overloading(重载)

例,与上述同名的real,其可通过\(参数个数、类型,返回值\)类型等区分。

void real(double r) {re = r;}

但是

complex(double r = 0, double i = 0)
	:re(r), im(i)
{ }

complex() : re(0), im(0){}

\[不能同时出现$$; 实例化例子 ```C++ { complex c1; complex c2(); ... } ``` 将出现问题。 ### 放在private区 构造函数放在private区将不能外界被创建对象。 示例 ```c++ class A { public: static A& getInstance(); //Singleton --单体,单件的意思 setup(){...} private: A(); A(const A& rhs); ... }; A& A::getInstance() { static A a; return al } ``` > 只有一份A,不允许外界创建。 > > 外界要使用A ,不能使用传统的创建方式,可以采用以下方式 > > ```C++ > A::getInstance().setup(); > ``` ## const常用成员函数 ```c++ class complex { public: complex (double r = 0, double i = 0) : re(r), im(i) {} complex& operator +=(const complex&); double real() const {return re;} double imag() const {return im;} private: double re, im; friend complex& __doapl(complex*, const complex&); }; ``` > Class中的函数分为可以改变数据内容和不能改变数据内容的,不会改变 数据内容的马上加上``const``。 > > 可以加的话一定加。 两个例子 ```C++ //加的话 { complex c1(2,1); cout << c1.real(); cout << c1.imag(); }//是没有问题的 //假如不加,但是使用者这样定义常量 { const complex c1(2,1); //定义一个常量 cout << c1.real(); cout << c1.imag(); } ``` > 上述情况(即定义时不加const, 但是使用者在定义时加了const),意思是我在定义时表明变量数据会改变,但是使用者加const指出这个值不能改变,这样将产生冲突。编译器会发出一些信息。 ## 参数传递:pass by value vs. pass by reference(to const) <img src="https://imghome-1302941983.cos.ap-beijing.myqcloud.com/img/202210141731778.webp" alt="image-20221014173114619" style="zoom: 67%;" /> 尽量不要使用pass by value, 像传包一样把整体传过去。``by reference``,传递地址。 ```C++ { complex c1(2,1); complex c2; c2 += c1; cout << c2; } ``` ## 返回值传递 > return by value vs. return by reference(to const) 如果可以的话, 返回值传递也尽量``by reference``。 ```C++ class complex { public: complex(double r = 0. double i = 0) : re(r), im(i) {} complex& operator += (const complex&); double real() const {return re;} double imag() const {return im;} private: double re,im; friend complex& __doapl(complex*, const complex&); }; ``` ## 友元 ```C++ inline complex& __doapl (complex* ths, const complex&r) { ths-> re += r.re; ths-> im += r.im; return *ths; } ``` ### 相同class的各个objects互为友元(friend) ```C++ class complex { public: xxx int func(const complex& param) { return param.re + param.im;} private: double re, im; } ``` > 知道为什么 ## class body 外的各种定义(definitions) >探讨什么情况下可以``pass by reference` > >什么情况下可以``return by reference`` <img src="https://imghome-1302941983.cos.ap-beijing.myqcloud.com/img/202210171718953.webp" alt="image-20221017171759989" style="zoom:67%;" /> **return** - 假如产生结果需要存储在函数内部新开辟的local变量里,则不可以,因为离开函数区变量将销毁; - 若生成结果是对已有变量(内存空间)进行修改,则可以,如上图。 参数的传递或返回值的传递首先考虑引用(reference),然后再考虑有没有问题。 ## Summary **对于一个class** - 数据一定封装在private里 - 参数尽可能是``pass by reference`` - 返回时也尽量``pass by reference`` - 类的本体能加const就加const - 默认构造函数的实现\]

posted @ 2023-10-01 18:35  travis-ge  阅读(4)  评论(0编辑  收藏  举报