C/C++程序员面试宝典(二)

面向对象基础知识
1、面向对象3个要素:封装、继承、多态。面向对象中所有的对象都可以归属为一个基类。

类成员
2、成员变量的访问方式:
private:可以被该类的成员方法和友元函数访问,但不能被该类的对象访问。
protected:可以被该类的成员方法、友元函数及子类的方法访问,但不能被该类的对象访问。
public:可以被该类的成员方法、友元函数及子类的方法访问,也能被该类的对象访问。

多态
3、动态多态:继承+虚函数(常用)
静态多态:泛型,STL(模板技术)

template <typename vv>
void fun(const vv& v){
	v.fun1(); //这样就可以在main中,根据传入的fun中参数的对象类型,去调用各自类中的fun1方法
}

函数多态:重载(相同的函数名,不同的参数列表,其中有一种特殊的,const成员函数和非const成员函数同样可以形成重载)

class Test  
{  
protected:  
    int x;  
public:  
    Test (int i):x(i){ }  
    void fun() const{  
        cout << "fun() const called " << endl;  
    }  
    void fun(){  
        cout << "fun() called " << endl;  
    }  
};  
   
int main()  
{  
    Test t1 (10);  
    const Test t2 (20);  
    t1.fun();  //fun() called
    t2.fun();  //fun() const called
    return 0;  
}

宏多态:

#define ADD(A,B) (A)+(B)
int main()
{
	int i = ADD(1,2); //两个整数相加
	string s = ADD("hello","world"); //两个字符串相加	
}

继承
4、派生类总是可以自动转换为基类的引用类型,基类转换为派生类需要在确定安全的情况下,使用强制转换来进行转换。

复制构造函数
5、深拷贝和浅拷贝
浅拷贝:只是对对象中的数据成员进行简单的复制(默认复制构造函数)
在这里插入图片描述

class Student
{
private:
	int num;
	char *name;
public:
	Student();
	~Student();
};
Student::Student()
{
	name = new char(20);
	cout << "Student" << endl;
}
Student::~Student()
{
	cout << "~Student " << (int)name << endl;
	delete name;
	name = NULL;
}

int main()
{
	Student s1;
	Student s2(s1);// 复制对象
	
	return 0;
}

执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,这会导致什么问题呢?name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会导致崩溃!

深拷贝:重新分配空间(重载默认的拷贝构造函数)
在这里插入图片描述

Student::Student(const Student &s)
{
	name = new char(20);
	memcpy(name, s.name, strlen(s.name));
	cout << "copy Student" << endl;
}

执行结果:调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。

6、有3种情况会使用复制构造函数:
一个对象以值传递的方式传入函数体;
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。

函数的定义
7、求最大公约数:通过不断的求余数,并更新第一个数的值为当前第二个数的值,直到余数为0,返回第一个数。(辗转相除法)

int gcd(int v1, int v2) {
	while (v2) {
		int temp = v2;
		v2 = v1 % v2;
		v1 = temp;
	}
	return v1;
}

8、在类内部声明或定义的成员函数叫做内联(inline)函数:函数的代码被放入符号表中,在使用时直接进行替换,适用于代码量较小的函数。

class temp{
  public:
  int  amount;
  temp(int amount){
  	this->amount = amount;
  }

  void test(){ //默认的都是内联函数,可以不加inline
	cout << "default inline" << endl;
  }  

  //普通成员函数,在类内声明时前面可以不加inline
  void print_amount();
}

//在类外定义函数体,必须在前面加上inline关键字
inline void temp:: print_amount(){
  cout << amount << endl;
}

类成员函数
9、外部类可以使用宏定义等特殊的方法来实现访问类的私有成员,但是是一种非正规的方法,会破坏类的封装性。

#define private public
#define protected public

模板
10、函数模板技术使得程序能够使用不同的参数类型调用相同的函数,相比于重载写的代码量还要少。(是一种多态的体现)

template <typename T>
T Add(T a, T b)
{
	T result;
	result = a + b;
	return result;
}

int main()
{
	cout << Add(1, 2) << endl; //3
	cout << Add(string("1"), string("2")) << endl; //12

	return 0;
}

11、类模板:常用于建立包含其他类型的容器,例如动态数组、队列、链表和堆栈等。

template<class T> 
class A{
public: 
	T a; 
	T b; 
	T hy(T c, T &d);
};

容器
12、顺序容器:数组和链表的推广,以严格的线性形式组织在一起。
vector<T>、deque<T>、list<T>
vector可以通过at()或[]来访问其中的元素。
关联容器:提供一个Key实现对元素的高效查找和读取,适用于插入和删除操作。
map(Key,Value)、set、multimap(Key,Value)、multiset
vector、map、set的区别:
a. map和set使用了非常高效的平衡二叉树:红黑树(查找、插入、删除等操作的时间复杂度为O(logn) )。
b. set和vector的区别在于set不能包含重复的数据,而vector可以。
c. set和map的区别在于set只含有Key,而Map有一个Key和Key所对应的Value两个元素。

13、迭代器的范围:begin(指向第一个元素)和end(指向最后一个元素的下一个位置,并不是容器的元素)之间的范围。

泛型编程
14、以独立于任何特定类实现的方式编写代码,针对不同的类型提供通用的实现。(基础就是模板技术)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值