qq_41945416 2025-10-30 15:39 采纳率: 90.6%
浏览 4
已结题

关于mfc函数未声明虚函数但被重写的问题

看以下mfc的编程代码

class CDemo
{
public:
      /*virtual*/ void DemoMian()
      {
        AfxMessageBox(_T("1"));
      }
};

class CDemoEx : public CDemo
{
public:
      void DemoMian()
      {
        AfxMessageBox(_T("2"));
      }
};

1.1程序员粗心大意,在编程的时候忘了向父类成员函数添加关键字 virtual。所以当函数通过对象调用的时候,弹出的消息框内容应该是1,还是2呢?
1.2父类的成员函数是公有属性,继承之后能不能变成保护或私有属性?或者反过来,父类的成员函数是私有或保护属性,继承之后能变成公有属性吗?
1.3 我观察到对话框的构造函数不带关键字 virtual,那也就意味着构造函数只能重载,不能重写吗?

  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-30 15:50
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:生活就像一杯白开水,你往里面加什么,它就是什么味道。
    .

    1.1 函数重写问题

    当父类函数没有声明为virtual时,子类中的同名函数不会形成真正的多态重写,而是函数隐藏

    CDemo demo;
    demo.DemoMian();        // 输出 "1"
    
    
    CDemoEx demoEx;
    demoEx.DemoMian();      // 输出 "2"
    
    
    CDemo* pDemo = new CDemoEx();
    pDemo->DemoMian();      // 输出 "1"(关键!)
    

    结果分析:

    • 通过对象直接调用时,调用的是各自类中定义的函数
    • 通过父类指针调用时,由于没有虚函数表机制,调用的是指针类型(CDemo)的函数

    1.2 继承属性变化问题

    继承规则:

    • 公有继承(public):保持原有访问级别
    • 保护继承(protected):公有→保护,其他不变
    • 私有继承(private):所有成员→私有
    class Base {
    public:
        void publicFunc() {}
    protected:
        void protectedFunc() {}
    private:
        void privateFunc() {}
    };
    
    
    // 公有继承
    class PublicDerived : public Base {
        // publicFunc: public
        // protectedFunc: protected  
        // privateFunc: 不可访问
    };
    
    
    // 保护继承  
    class ProtectedDerived : protected Base {
        // publicFunc: protected
        // protectedFunc: protected
        // privateFunc: 不可访问
    };
    
    
    // 私有继承
    class PrivateDerived : private Base {
        // publicFunc: private
        // protectedFunc: private
        // privateFunc: 不可访问
    };
    

    重要限制: 访问级别只能降低或保持不变,不能提升。

    1.3 构造函数特性

    构造函数确实不能声明为虚函数,原因:

    1. 内存分配时机:构造函数调用时对象尚未完全创建,虚函数表还未建立
    2. 语义冲突:虚函数用于多态,而构造函数的目的是创建特定类型的对象
    3. 语法禁止:C++语言标准明确禁止虚构造函数

    构造函数的正确使用:

    class Base {
    public:
        Base() {}                    // 构造函数
        Base(int value) {}           // 重载构造函数
        virtual ~Base() {}           // 虚析构函数(推荐)
    };
    
    
    class Derived : public Base {
    public:
        Derived() : Base() {}        // 调用父类构造函数
        Derived(int value) : Base(value) {}  // 调用父类重载构造函数
    };
    

    总结:

    • 构造函数可以重载,但不能重写
    • 析构函数应该声明为虚函数(特别是在多态使用场景中)
    • 通过构造函数重载实现不同的构造方式,通过虚函数实现运行时的多态行为
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月8日
  • 已采纳回答 10月31日
  • 创建了问题 10月30日