【C++学习】面向对象(oop)


一、头文件与命名空间

1. 头文件是什么

例:A.cpp, A.h, B.cpp
A.h 头文件 中写入类声明、函数原型、#define;
A.cpp实现文件 写入类函数的定义实现;
B.cpp调用文件 通过一个宏命令 “#include” 调用A.h中的类和函数等
[注1] 头文件无需编译,只需在源文件预处理时被合并
[注2]#include功能仅是简单的文本替换
[注3]系统头文件用< >, 自定义头文件用" "

//头文件的防御式编程
#ifndef A_H
#define A_H

//...

#endif

2.几个特殊情况

(1)static修饰变量、函数可以写在.h文件中
(2)inline内联函数定义可以写在.h文件中
(3)模板类型可以写在.h中,模板在调用时才编译

3.命名空间

区分不同库中相同名称的函数、类、变量

  1. 定义
namespace namespace_name {
   // 代码声明
}
  1. 调用
name::code;  // code 可以是变量或函数
//后续的代码将使用指定的命名空间中的名称。
using namespace namespace_name;

//指定命名空间中的特定项目
using std::cout;

二、面向对象编程

1.语法点

1.1 private、public、protected

(1)数据防止泄露,通常为private。
(2)protected可由派生类访问。
(3)同一类的不同对象可以相互访问private变量、函数。

1.2 inline

(1)内联函数的两种写法:

  1. 定义写在类内
  2. 定义写在类外,加上inline前缀

(2)内联函数只是一种建议,具体实现由编译器决定
(3)内联函数减少了运行栈保存变量的开销

1.3 const

(1)const成员变量:不应被改变
(2)const成员函数:不应改变成员变量的值
(3)const对象:只能访问被 const 修饰的成员函数、变量
(4)const int* p与int* const p

1.4 static

static类型属于类,对象间共享内存
(1)static成员变量
(2)stattic成员函数

  1. 只能访问静态成员变量
  2. 声明时加static,定义时不加static

1.5 friend

【友元函数】
(1)友元函数不是类的成员函数,在类中声明,类外定义
(2)友元函数有权访问类的private、protected、public函数和变量。
(3)友元函数必须通过参数传递对象才能访问类的成员
【友元类】
(1)友元类中的所有成员函数都是另外一个类的友元函数。

2.面向对象的难点问题

2.1 构造函数

  1. 初始化问题
    complex(double r, double i):re(r),im(i) {}
    提前初始化,而不是用assign赋值有利于提高性能。
  2. 构造函数可以重载
  3. private中的构造函数:单例模式

2.2 操作符重载问题

  1. 操作符重载的两种方法
    成员函数方法:a.op(b),含有返回值满足连续op的情况;
    全局函数+友元函数方法:op(a,b);
  2. 不能重载的操作符
    . ?: :: sizeof
  3. 运算符重载不改变优先级

2.3 copy问题

  1. 深拷贝 和 浅拷贝
    浅拷贝:类内变量创建副本,类内指针共享内存
    深拷贝:需要自定义重载
  2. 默认拷贝为浅拷贝,含指针的类可能出现内存泄露
  3. 拷贝构造copy ctor 和 拷贝赋值copy op=
    copy op= 等价于 自我赋值检测 + delete_self + copy ctor

2.4 析构函数问题

  1. 类内存在动态分配内存的情况时(往往表现为含指针),需要添加析构函数
  2. 普通对象:消亡时自动调用析构函数
  3. 指针对象:注意new与delete的匹配问题

2.5 值、指针、引用

2.5.1 value 与 reference
  1. value:默认为浅拷贝,内存开销大
  2. reference:变量别名,共享内存
  3. 返回局部变量时,不能声明为reference,因为局部变量在函数结束时销毁
2.5.2 reference 与 pointer
  1. pointer可能为null,reference必须被初始化
  2. pointer可以改变,reference不能更改

二、示例

1.类不含指针(Complex)

代码如下(示例):

#include<iostream>

using namespace std;

class Complex{

private:
	double real, imag;
public:
	//默认构造函数
	Complex(){ } 
	//重载构造函数 + 初始化列表 
	Complex(double r, double i): real(r), imag(i){ }
	//成员函数 的 操作符重载 + 临时对象 
	Complex operator+(const Complex& c) const{
		//返回local变量不能使用reference 
		return Complex(real + c.real, imag + c.imag); 
	}
	//全局函数 的 操作符重载 + 友元函数 
	friend ostream& operator<<(ostream& os, Complex& c);
	friend Complex& operator+=(Complex& c1, const Complex& c2);
	/*
	Complex& operator+=(const Complex& c2)
	{
		this->real += c2.real;
		this->imag += c2.imag; 
	} 
	*/ 
};

Complex& operator+=(Complex& c1, const Complex& c2){
	c1.real += c2.real;
	c1.imag += c2.imag;
	return c1;
}
ostream& operator<<(ostream& os, Complex& c){
	os << "(" << c.real << "," << c.imag << ")";
	return os;
}

int main()
{
	Complex c1;
	Complex c2(5,5);
	const Complex c3(5,5);
	c2 += c3;
	c1 = c2 + c3;
	cout<<c1<<endl;
} 


2.类含指针(String)

代码如下(示例):

#include<iostream>
#include<cstring>
/*
注: 
cstring:c++版的string.h 
string: stl范畴
string.h: c语言库,c++兼容 
*/ 


using namespace std;

class String{
private:
	char* m_data;
public:
	String(const char* cstr = 0);
	//copy ctor 
	String(const String& s);
	//copy op=
	String& operator=(const String& s);
	//析构函数
	~String(); 
	
	char* get_str() const{
		return m_data;
	}
	
	friend ostream& operator<<(ostream& os, const String& s);
};

//注:不能同时在 声明 和 定义 中写默认参数 
inline
String::String(const char* cstr){
	if(cstr){
		m_data = new char[strlen(cstr) + 1];
		strcpy(m_data, cstr);
	}
	else{
		m_data = new char[1];
		*m_data = '\0';
	}
	
}

inline
String::~String(){
	delete[] m_data;
}

inline
String::String(const String& s){
	//深拷贝 
	m_data = new char[ strlen(s.m_data) + 1 ];
	strcpy(m_data, s.m_data); 
}

inline
String& String::operator=(const String& s){
	//step1:检查自我赋值
	//注意指针细节:&s,this:地址;s,*this:string内容 
	if(&s == this){
		return *this;
	} 
	//step2:删除空间
	delete[] m_data;
	//step3:copy ctor
	m_data = new char[ strlen(s.m_data) + 1 ];
	strcpy(m_data, s.m_data);
	return *this; 
}

ostream& operator<<(ostream& os, const String& s)
{
	os<<s.get_str();
	return os;
}

int main()
{
	const String s2("duan");
	const String s3("shuai");
	String s1(s2);
	cout<<s1<<endl;
	s1 = s3;
	cout<<s1<<endl;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值