`
tcspecial
  • 浏览: 911663 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

C++ 妙用virtual 回调子类方法

阅读更多

     C++中关键字virtual主要用于多态,子类重写父类方法,从而提供更灵活的实现逻辑. 在QT里面,我们经常会继承QWidget, 然后在子类中重写mouseMoveEvent()这些事件,当鼠标移动时系统执行子类方法逻辑,一直都很纳闷这是怎么实现的, 如何将子类函数指针传入到父类, 当相应事件发生时,进而执行子类鼠标移动方法. 

 

    1. virtual的基础用法 

// 父类
class A
{
public:
	A(){}
	~A(){}
	
	virtual void print()
	{
		printf("A hello\n");
	}
};

// 子类
class B:public A
{
public:
	B():A(){}
	~B(){}
	
public:
	void print()
	{
		printf("B hello\n");
	}
};

// 测试
B *b=new B;
A *a=b; // 重点:将A指针指向B
a->print();  // 此时执行B类方法,打印 "B hello"

    通过上面代码发现,直接将A指向B,就能执行B方法. 这样我们可以在构造方法时,将类指针指向当前类,就达到了注入子类的目的 

 

    2. 传入子类指针

// 前置声明,增加中间类,用来初始化子类指针 
class C; 
// 父类 
class A
{
	friend class C;
public:
	A();
	{
		c=new C;
		
		// 初始化成员指针 
		init();
	}
	
	~A(){}
	
	void init()
	{
		c->a=this; // a指向当前类,如果当前类为派生类,则this指针就表示派生类,这样就传入了子类指针 
		
		/// 错误
		c->run(); // 调用方法
	}
	
	virtual void print()
	{
		printf("A hello\n");
	}
	
private:
	C *c;
};

// 子类
class B:public A
{
public:
	B():A(){}
	~B(){}
	
	void print()
	{
		printf("B hello\n");
	}
};

// 增加C类,用来对成员变量A赋值
class C:public QThread
{
public:
	C(){}
	~C(){}
	
	void run()
	{
		a->print();
	}
private:
	A *a;
};


// 测试
B *b=new B();  // 打印 "A hello"

    当调用B构造函数时, 首先构造A,执行c->a=this; 将B赋值给A, 接下来执行run()方法, 按理说应该打印B的print方法,怎么仍然执行A了,难道在构造B时,执行A构造方法时,此时的this不是B.  经打印发现 this 的地址值0x3d2f10与B一致, 原来此时B未完成实例化,系统无法执行B方法.

 

   3. 从构造函数中分离任务,让其完成实例化,从而执行B类方法

// 前置声明,增加中间类,用来初始化子类指针 
class C; 
// 父类 
class A
{
	friend class C;
public:
	A()
	{
		c=new C;
		init(); // 初始化
	}
	
	~A(){}
	
	void init()
	{
		c->a=this; // a指向当前类,如果当前类为派生类,则this指针就表示派生类,这样就传入了子类指针 
	}
	
	virtual void print()
	{
		printf("A hello\n");
	}
	
private:
	C *c;
};

// 子类
class B:public A
{
public:
	B():A(){}
	~B(){}
	
	void print()
	{
		printf("B hello\n");
	}
};

// 增加C类,用来对成员变量A赋值
class C:public QThread
{
public:
	C()
	{
		start(); // 启动线程
	}
	
	~C(){}
	
	void run()
	{
		sleep(2);
		a->print();
	}
private:
	A *a;
};

// 测试
B *b=new B(); // 成功打印 "B hello"
 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics