using

#include "hjcommon.hpp"

using namespace std;
HJ_NS_USING

class Parent
{
public:
	void say() { cout << "Parent say no arg" << endl; }
	void eat(int a) { cout << "Parent eat one arg" << endl; }
	void eat(int a, int b) { cout << "Parent eat two arg" << endl; }
};

class Child : public Parent
{
public:
	void eat (int a) { cout << "Child eat one arg" << endl; }
	// c++98中当子类重写了父类某一eat函数时,子类对象就无法用 . 调用父类重载的其他eat函数,只能使用 Parent::eat 方式来调用。如果子类未重写,可以使用 .和:: 两种方式调用
	// c++11中引入using,作用:暴露父类Parent所有名为eat的函数,当子类重写父类某一eat函数后,让子类对象依然可以使用 . 调用未重写父类的其他eat函数
	using Parent::eat;
};

int main_2_3_7(int argc, char *argv[])
{
	Child c;
	c.say(); // 子类没有重载父类的say()函数时,可以使用 .和:: 调用父类的say()函数,如果重载了就只能使用 :: 调用
	c.Parent::eat(1); // :: 调用父类函数
	c.eat(1); // 调用子类本身eat函数
	c.eat(1, 2); // using暴露父类 eat(int, int) 函数
	return 0;
}

virtual、override、final

#include "hjcommon.hpp"

using namespace std;
HJ_NS_USING

class Human
{
public:
	// virtual的作用是发生多态,父类指针指向子类对象(有继承不一定能发生多态)。 当不需要继承的时候不要加virtual修饰,virtual修饰的类会生成虚函数表,会消耗性能
	virtual void say() final { cout << "Human say." << endl; } // virtual与final可以同时修饰一个函数,表现为final(c++11引入),不可继承
	virtual void walk() { cout << "Human walk." << endl; }

	virtual ~Human() = default;
};

class Man : public Human
{
public:
	// override c++11引入,表示重写父类该函数,若父类该函数未用virtual修饰,编译会报错。 override后依然可以用 Human::walk 调用到父类的函数
	virtual void walk() override { cout << "Man walk." << endl; }

	virtual ~Man() = default;
};

class A final // 被final修饰的类不能被继承,哪怕函数修饰为virtual
{
public:
	virtual void abc() {}
	virtual ~A() = default;
};
//class B : public A
//{
//};

int main_2_3_8(int argc, char *arv[])
{
	Human *human = new Man;
	human->Human::walk();
	return 0;
}

friend

#include "hjcommon.hpp"

using namespace std;
HJ_NS_USING

// 友元函数
class Demo
{
private:
	int num = 0;
	void say() const { cout << "private say." << endl; } // 因为 happy 函数参数是const,所以 say声明成const,常对象只能调用常量函数

	friend void happy(const Demo& demo); // friend函数不是类的成员函数,类似全局函数(但无法用static修饰),只是声明在类中,表示该函数可以调用类private,protected成员
};
void happy(const Demo& demo)
{
	cout << "friend func : " << demo.num << endl;
	demo.say();
}

// 友元类,友元关系不能被继承、是单向的、没有传递性
class B; // 前置声明
class A;
class C
{
public:
	void putA(int num, A& a);
};
class A
{
private:
	int num = 0;
	friend class B; // 声明类B是此类的友元类,表示类B所有成员函数中都能调用此类的private,protected成员
	friend void C::putA(int, A&); // 友元成员函数,类C中只有putA函数可以调用此类的private,protected成员
};
class B
{
public:
	void callA(int num, A& a)
	{
		a.num = num;
		cout << "friend class : " << a.num << endl;
	}
};
// 友元成员函数
void C::putA(int num, A& a)
{
	a.num = num;
	cout << "friend class func : " << a.num << endl;
}

int main_2_3_9(int argc, char *argv[])
{
	// 友元函数
	Demo demo;
	happy(demo);

	// 友元类,友元关系不能被继承、是单向的、没有传递性
	A a; B b; b.callA(23, a);

	// 友元成员函数
	C c; c.putA(44, a);

	return 0;
}

RTTI、dynamic_cast、typeid()、type_info

#include "hjcommon.hpp"

using namespace std;
HJ_NS_USING

class Animal
{
public:
	virtual void walk() { cout << "animal walk." << endl; }
	virtual ~Animal() = default;
};
class Dog : public Animal
{
public:
	void walk() { cout << "Dog walk." << endl; }
};

int main(int argc, char *argv[])
{
	// RTTI: (Run Time Type Identification) 运行时类型识别
	// RTTI的两个运算符:dynamic_cast<>()、typeid(),要让这两个运算符正常工作,基类必须有一个虚函数(没有虚函数(包含虚析构)继承时就没有虚函数表,就无法动态绑定,就无法多态)

	// dyanmic_cast
	Animal *animal = new Dog;
	Animal& ani = *animal;
	Dog& d = dynamic_cast<Dog&>(ani); // 基类若无虚函数,dynami_cast编译会报错
	d.walk();

	// typeid(类型) 也可能 typeid(表达式),作用:拿到对象类型信息,typeid()返回一个常量对象的引用,这个引用的类型是标准库里的 type_info
	Dog *dog = new Dog;
	cout << typeid(*animal).name() << endl; // 3Dog,若基类Animal中没有虚函数,此打印为: 6Animal ,不同平台 typeid().name() 可能显示的名称不一样
	cout << typeid(ani).name() << endl; // 3Dog,若基类Animal中没有虚函数,此打印为: 6Animal
	cout << typeid(animal).name() << endl; // P6Animal,若基类Animal中没有虚函数,此打印仍为: 6Animal ,这里注意引用与指针的区别。。
	cout << typeid(dog).name() << endl; // P3Dog

	// type_info == !=
	const std::type_info &ta = typeid(*animal);
	const type_info &td = typeid(*dog);
	ta.name(); // name()函数返回的是c语言风格的字符串
	if (ta == td) // 比较类型时,带上 * 。若基类Animal中没有虚函数,那么此判断就不会为真,有就为真
		cout << "equals." << endl;
	else
		cout << "not equals." << endl;

	return 0;
}

2_3_7 using、virtual、override、final、friend、RTTI、dynamic_cast、typeid、type_info

相关文章:

  • 2021-10-07
  • 2021-10-12
  • 2021-06-27
  • 2022-12-23
  • 2021-08-28
  • 2021-06-24
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-07-12
  • 2021-08-21
  • 2022-01-01
  • 2022-12-23
  • 2021-09-27
  • 2021-12-22
  • 2021-11-05
相关资源
相似解决方案