C++必看:列表初始化、不能声明为虚函数的、const同名函数的调用优先级问题、指针和引用的区别

必须通过列表来进行初始化

以下成员必须通过列表来初始化而不能在构造函数体内初始化。

  • const修饰的类成员变量:必须通过初始化列表初始化并且一旦初始化不可改变
  • 引用变量成员:必须在创建时绑定到一个对象
  • 带有引用的类变量
  • 类成员是其他类并且该类没有默认的构造函数:通过列表进行初始化
  • 父类没有默认的构造函数

不能声明为虚函数的

在C++中,并非所有函数类型都可以被声明为虚函数。以下是不能被声明为虚函数的函数类型的详细说明:

  1. 构造函数(Constructors)

    构造函数不能被声明为虚函数。这是因为虚函数机制依赖于虚表(vtable),而虚表是在对象构造完成后才完全初始化的。在构造函数执行时,对象尚未完全创建,因此无法通过虚函数机制进行动态分派。此外,构造函数的目的是初始化对象,其调用顺序由语言规则严格定义,不需要动态多态性。

  2. 静态成员函数(Static Member Functions)

    静态成员函数不能被声明为虚函数。虚函数的动态分派依赖于对象的实例,而静态成员函数属于类本身,与具体对象无关。因此,静态成员函数没有“this”指针,无法通过虚表进行动态绑定。

  3. 全局函数(Non-Member Functions)或友元函数(Friend Functions)

    全局函数和友元函数不属于类的成员函数,因此无法被声明为虚函数。虚函数机制仅适用于类的成员函数,以便实现运行时多态性。

  4. 内联函数(Inline Functions)

    内联函数原则上可以被声明为虚函数,但是虚函数表示多态时不能进行内联,但需要注意其实际行为。如果内联函数被声明为虚函数,并且在编译时调用点能够确定具体的函数版本(例如通过对象而非指针或引用调用),编译器可能会内联优化而忽略虚函数机制。然而,通过指针或引用调用时,虚函数的动态分派仍然会生效。因此,虽然内联函数可以是虚函数,但内联和虚函数的结合可能导致行为上的复杂性。

关于const同名字函数的调用优先级问题

在 C++ 中,当一个类中有同名函数(如 f() 和 f() const)时,编译器会根据调用者的上下文(特别是对象的 const 性)来决定调用哪个版本。这种选择与以下因素有关:

  1. 指针的 const 性
    • p 的类型是 A*,即一个指向非 const A 的指针。
    • 这意味着通过 p 可以调用非 const 成员函数,也可以调用 const 成员函数(因为非 const 对象隐式地也可以被当作 const 对象处理)。
  2. 重载解析规则
    • 当有多个同名函数(如 void f() 和 void f() const)时,C++ 编译器会选择“最匹配”的版本。
    • 对于非 const 对象(或非 const 指针/引用),编译器优先选择非 const 版本的函数,因为它不需要额外的 const 转换。
    • 只有当对象被显式声明为 const(或通过 const 指针/引用访问)时,才会调用 const 版本。
  3. 虚函数的动态绑定
    • p 指向的是一个 B 对象,且 A::f() 是虚函数,因此调用时会动态绑定到 B::f()。
    • 但这里的“动态绑定”只决定调用哪个类的实现(A 还是 B),而是否选择 const 版本是由调用时的静态类型(A*)和上下文决定的
using namespace std;
class A{
    public:
        virtual void f() { cout << "A::f() "; }
        void f() const { cout << "A::f() const "; }
};
class B : public A {
    public:
        void f() { cout << "B::f() "; }
        void f() const { cout << "B::f() const "; }
};
void g(const A* a) {
    a->f();
}
int main(int argc, char *argv[]) {
    A* p = new B();
    p->f();//这里调用时候优先被调用非const的版本
    g(p);//const参数传入,只能调用const版本
    delete(p);
    return 0;
}

关于指针和引用的区别

1) 引用必须被初始化,指针不必。

2) 引用初始化以后不能被改变,指针可以改变所指的对象。

3) 不存在指向空值的引用,但是存在指向空值的指针。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值