首页 > 编程语言 >Effective C++ 规则41:了解隐式接口和编译期多态

Effective C++ 规则41:了解隐式接口和编译期多态

时间:2025-01-23 21:30:17浏览次数:3  
标签:Effective 多态 C++ 编译 接口 类型 print type

1、隐式接口

C++ 中的 隐式接口 是指类或者模板中不显式声明为接口的一部分,但仍然可以像接口一样使用的成员或方法。隐式接口通常指那些不显式声明为虚函数的函数或者方法,但在多态上下文中仍然能表现出类似接口的行为。
隐式接口通常出现在模板编程中,尤其是 模板类型推导、SFINAE(Substitution Failure Is Not An Error) 技术或者 类型特性(type traits)等编译期机制中。它使得类和函数可以灵活地与多种类型协作,而无需显式继承或声明接口。考虑下面的例子:

// 隐式接口的示例:类的模板
template <typename T>
class Printer {
public:
    void print(const T& value) {
        value.print();  // 假设 T 类型有一个 print() 方法
    }
};

这里的 Printer 类依赖于类型 T 是否有 print() 方法。这并没有显式声明接口,但是如果类型 T 提供了 print() 方法,那么 Printer 就能使用它。这就是隐式接口的一个示例:Printer 并不直接约束 T 必须实现 print() 方法,但只要 T 提供了 print(),它就能在 Printer 中使用。

class A {
public:
    void print() const {
        std::cout << "Class A" << std::endl;
    }
};

class B {
public:
    void print() const {
        std::cout << "Class B" << std::endl;
    }
};

int main() {
    Printer<A> printerA;
    printerA.print(A());  // 输出 "Class A"
    
    Printer<B> printerB;
    printerB.print(B());  // 输出 "Class B"
}

这个例子中,A 和 B 类型并没有显式实现一个共同的接口或基类,但是 Printer 类可以接受这两个类型,并且调用它们的 print() 方法。这就是通过隐式接口实现的行为。

2、编译时多态

C++ 的 编译期多态(compile-time polymorphism)是指通过模板和编译期特性(如模板特化、SFINAE 等)在编译时进行的多态性选择。在编译期就根据类型特征来决定具体的行为,从而实现类似运行时多态的灵活性,但这种多态性是在编译时决定的。编译期多态最常见的实现方式是使用 模板特化 或 constexpr 函数。与运行时多态(基于虚函数)不同,编译期多态在编译时已经确定了所有类型和行为,因此非常高效,不需要运行时的动态派发开销。考虑下面的例子:

template <typename T>
void print_type(const T& value) {
    std::cout << "Unknown type" << std::endl;
}

template <>
void print_type<int>(const int& value) {
    std::cout << "Integer: " << value << std::endl;
}

template <>
void print_type<double>(const double& value) {
    std::cout << "Double: " << value << std::endl;
}

int main() {
    print_type(42);         // 输出 "Integer: 42"
    print_type(3.14);       // 输出 "Double: 3.14"
    print_type("Hello");    // 输出 "Unknown type"
}

在这个例子中,print_type 函数通过模板特化实现了编译期的多态行为。虽然没有虚函数和继承,但编译器会根据传入的类型选择适当的特化版本。这种方法在编译时决定了调用哪个函数,效率很高。

3、编译期多态和类型特性

C++11 引入的 类型特性(type traits) 使得编译期多态变得更加灵活。类型特性允许你在编译时对类型进行检查,从而根据不同的类型执行不同的操作。例如,我们可以使用 std::is_integral 来检查类型是否为整数类型:

#include <iostream>
#include <type_traits>

template <typename T>
void print_type(const T& value) {
    if (std::is_integral<T>::value) {
        std::cout << "Integer: " << value << std::endl;
    } else {
        std::cout << "Not an integer" << std::endl;
    }
}

int main() {
    print_type(42);         // 输出 "Integer: 42"
    print_type(3.14);       // 输出 "Not an integer"
}

在这个例子中,std::is_integral::value 是一个编译时常量,决定了是否执行整数类型的逻辑。这就是编译期多态的一种形式,利用类型特性在编译阶段就选择不同的代码路径,而不是依赖运行时的动态类型。

4、隐式接口与编译期多态的关系

  • 隐式接口 允许我们在不显式声明接口的情况下,实现不同类型的多态行为。这使得我们的代码更加通用,可以与多种类型协作,而无需强制每个类型都实现某个显式的接口。
  • 编译期多态 通过模板编程和类型特性等机制在编译时选择不同的行为。这种选择是静态的,避免了运行时的性能开销,同时也让我们能够在编译时确定最合适的实现。

5、个人体会

读完规则41,我意识到,在 C++ 中,灵活的多态性不仅仅限于传统的基类与虚函数机制,还可以通过模板编程、类型特性等技术在编译时实现。隐式接口使得代码更加通用,编译期多态则通过静态选择提高了性能。

标签:Effective,多态,C++,编译,接口,类型,print,type
From: https://blog.csdn.net/xiaoan08133192/article/details/145312576

相关文章

  • async++库的使用示例
    1、普通异步函数如前面的博客介绍的,这个库中提供了async::spawn方法,这个方法通常用来启动异步函数,这个框架会利用线程池去完成函数,因此要注意数据安全。正因为将任务放到了单独的线程执行,并且还有调度开销,因此简单的任务最好不要使用这种方法,得不偿失。示例代码如下:voidd......
  • C++ 队列( queue )详解 加强版
    作者制作不易,关注、点赞、收藏一下吧!目录1.队列2.模拟队列2.1.入队(push)2.2.出队(pop)2.3.获取队首元素2.4.获取队尾元素2.5.获取队列长度2.6.判断队列是否为空3.直接使用队列(queue)3.1.普通队列3.1.1.入队(push)3.1.2.出队(pop)3.1.3.获取队首元素(......
  • 埃氏算法C++实现: 快速输出质数( 素数 )
    目录1.简介算法原理算法特点应用场景2.一般求素数方法3.埃氏算法求素数3.1.无动态分配3.2.有动态分配1.简介‌埃氏算法(EratosthenesSieve)‌,全称为埃拉托斯特尼筛法,是一种由古希腊数学家埃拉托斯特尼在公元前3世纪提出的古老而经典的算法,用于计算一定范围内的素数......
  • c++专题一
    C++框架&输入输出#include<iostream>usingnamespacestd;//写了这个之后使用标准库组件前面就不用写std::intmain(){​return0;}输入std::cin>>x输出std::cout<<"helloworld"<<std::endl;//std::endl用来换行格式化输出:#include<iomanip>//用于控制输出......
  • ACM 寒假第一讲:C++ 基础
    1.A-LongLoongProblemStatementForapositiveintegerX,theDragonStringoflevelXisastringoflength(X+3)formedbyoneL,Xoccurrencesofo,onen,andonegarrangedinthisorder.YouaregivenapositiveintegerN.PrinttheDragonStrin......
  • C++模板全解析:场景与注意点揭秘!
    C++作为现代编程语言中的一种,其强大功能和复杂性使得它在系统编程、应用开发等领域广受欢迎。其中,模板(Template)是C++语言中一个极为重要且强大的特性,它不仅提高了代码的复用性,还使得类型无关的编程成为可能。本文将详细介绍C++模板的基础知识,包括其概念、分类、常见应用场景及......
  • C++中static和const的区别和用法
    在C++中,static和const是两个关键字,它们各自有不同的用途和语法。下面是它们的主要区别和用法:const关键字const关键字用于声明一个常量,即该变量的值在初始化后不能被修改。用法:局部变量:voidfunc(){constinta=10;//a是一个常量,值为10,不能在函数内部修改......
  • 第一讲C++
    第一题LongLoongForapositiveintegerX,theDragonStringoflevelXisastringoflength(X+3)formedbyoneL,Xoccurrencesofo,onen,andonegarrangedinthisorder.YouaregivenapositiveintegerN.PrinttheDragonStringoflevelN.Noteth......
  • c++迷宫问题(migong)
    今天的题目叫“迷宫问题(migong)”,是“DFS深度优先搜索递归”一类的。题目描述设有一个N*N(2<=N<10)方格的迷宫,入口和出口分别在左上角和右上角。迷宫格子中分别放0和1,0表示可通,1表示不能,入口和出口处肯定是0。迷宫走的规则如下所示:即从某点开始,有八个方向可走,前进方格中数......
  • c++瓷砖
    今天的题目叫“瓷砖”,是“DFS深度优先搜索递归”一类的。题目描述在一个w×h的矩形广场上,每一块1x1的地面都铺设了红色或黑色的瓷砖。小谢同学站在某一块黑色的瓷砖上,他可以从此处出发,移动到上、下、左、右四个相邻的且是黑色的瓷砖上。现在他想知道,通过重复上述移动所能......