C++批判

2024-08-27 20:32
文章标签 c++ 批判

本文主要是介绍C++批判,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.如果能够直接控制构造函数与析构函数,我们不需要右值引用
右值引用有明显的微量机能浪费。移动时必须给指针赋nullptr。然后在析构时的delete里还会有if判定。

C++中,对象的构造与析构不能被以更低级的方式控制。假如有一个类,我们希望它不被构造。但C++规定了,如果一个类没有无能的默认构造函数,则不可能实现我所说的,就是阻止这个 默认内存块进行自动构造。GDI+就有这样的类,就是Gdiplus::Graphics类。这导致其使用起来很难实现效率最优。

所谓机能浪费,就是让计算机做多余的事情。

因此,需要有这样两个关键字:no_construct、no_destruct。前者阻止对象被自动构造。后者阻止对象被析构。
阻止对象自动构造的原因在于,希望在声明之后手动调用构造函数。
阻止对象自动析构的原因在于,保证之后将对象合理转移。
有了这两个东西,就不再需要怪物一样的右值引用了。
右值引用毫无价值,纯粹是一种荒谬的概念。我们需要正义的语言特性。
C++创造性地发明了构造函数和析构函数(当然,这不全是它的功劳),却没有使它们完备。希望新的C++标准能够使这对发明完备。
允许对象暂时不进行构造,手动控制构造函数。
允许对象不自动析构,保证之后对象将被合理转移,或者手动调用析构函数。
void func()
{
  object obj;    //obj未被构造。
  object obj();  //obj执行的是默认构造方法。
  
  no_construct object obj; //相当于“object obj;”。
  no_destruct object obj;
  
  //结尾处,obj将不会被析构。
}

2.模板就不能限定范围吗?

我阅读了本贾尼的书(书名忘了...最近一直在读),里面提到了“概念”这个概念。如果这个特性加入标准,则我下面的论述就毫无意义了。

但是这个概念终究没有加入标准(理由是,会更加严重地降低编译速度)。或许,新标准还是可以考虑类似的事情的。

我们需要这样的模板,能够控制实例化范围。这个范围可以称之为类型区间。因为模板管得太宽所造成的麻烦实在太多太多了。
有时候,举个例子:
有下面这些类型:
A,B,C,D,E,F,G,H,I,J,K,L,M,N
我们希望将一个模板应用到A-D,另一个同名模板应用到E-G,而H,I,J有自己的同名重载函数方法。
以现在的C++模板,这是不可能的。
你只能选择一个最大的范围,定义为模板,而其他的类型,需要特化方法的化,就只能一一重载了。
以后有新的类型,照样要一一重载。这太可恶了。
模板这种东西,本来就和宏差不多。如果我是语言发明者,我会让预处理器去处理模板。
但我不是。假如非得要实现这样的功能,没有很好的办法,只能定义两个或多个名称不同,参数一样的模板,然后通过重载函数的方法,对每个对象进行重载。
这,太麻烦了!我不喜欢这种过程。一一重载即使能使用宏,仍然是无聊乏味的工作。
template<typename T> void A_D_func(const T & r){ ... }
void func(const A & a){ A_D_func(a); }
void func(const B & b){ A_D_func(b); }
void func(const C & c){ A_D_func(c); }
void func(const D & d){ A_D_func(d); }


template<typename T> void E_G_func(const T & r){ ... }
void func(const E & e){ E_G_func(e); }
void func(const F & e){ E_G_func(f); }
void func(const G & g){ E_G_func(g); }


void func(const H & h){ ... }
void func(const I & i){ ... }
void func(const J & j){ ... }
如果有宏,可以这样:
#define MC_FUNC(X) void func(const X & x){ A_D_func(a); }
MC_FUNC(A)
MC_FUNC(B)
MC_FUNC(C)
MC_FUNC(D)
#undef MC_FUNC
我受够了。


我希望这样:
template<typename T(A,B,C,D)> void func(const T & r){ ... }
template<typename T(E,F,G)> void func(const T & r){ ... }
以上两个模板对实例化的范围进行了限定。第一个只对A,B,C进行实例化。第二个只对E,F,G进行实例化。
只有被用到的函数才真正被实例化,并非列表中出现的类型都会被实例化。
省去了好多麻烦。有多少时间浪费在了这么无聊的事情上呢?
3.我希望在已存在的类中添加方法
一旦一个类已经写就,就不可能往里面增添方法了。
比方说:
class C
{
   using me = C;
   me(){}
   me(int){}
   me(int,const word * s){}   //using word = wchar_t;
   void func(){}
};
我希望往C里面添加一个函数:
   void func2(){}
除非修改源代码,否则绝不可能往类里添加方法。
而很多既有的库的类都是已经封装好的。你总不能直接往那里面添加东西。这当然不行。
因此,可能还能使用一个技巧——继承。
而继承太麻烦了。继承最大的缺点是:不能继承构造函数!
构造函数是不能继承的,即使我只想在其上添加几个非常普通的方法函数。
我也不得不自己手写构造接口!
class CC:C
{
   me(){}
   me(int i):base(i){}
   me(int i,const word * s):base(i,s){}
   void func2(){}
}
我一头撞死算了!第3,4,5行一点意义都没有!这应该由编译器自动完成!
要实现这一点,要么增加关键字,要么定个规则。如果没有添加其他的数据成员,将自动继承基类构造函数。
后者比较现实。因此:
class CC:C{}
将自动继承基类的构造方法。然后我们就可以直接添加方法了。也是比较方便的。
但是,我还是希望能够在类的外部添加成员方法,哪怕其实际的调用方式与原生方法不太相同。
void CC:.func3(){ ... } //是的,新的符号:“:.”。
要调用func3,需要这样调用:
CC cc;
cc:.func3()
或许,可以统一定义外附类方法。外附类方法是以模板实现的。具体细节以后详细讲。
总之,我非常希望能够自行扩充现有类。
如果要求外接成员函数这样调用:
cc.func3(),必须考虑名字碰撞的问题。旧的类方法是不允许覆盖的。如果允许会产生很多问题。
因此扩展方法仅仅只有在名字未被使用的情况下才允许。
4.假如能够实现自定义语法
C++没有一个更好的预编译器。其宏与C语言几乎完全一样。这非常让人失望。我们需要一个更先进和强大的预编译器,以至于甚至连自定义语法的功能都能通过预编译器实现。
最好这个预编译器甚至能够控制符号的文本显示格式,比方说,字体的颜色,风格。
我想多了。这样的东西令人向往,然而或许不是C++追求的目标...

这篇关于C++批判的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1112707

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

使用C/C++调用libcurl调试消息的方式

《使用C/C++调用libcurl调试消息的方式》在使用C/C++调用libcurl进行HTTP请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试,libcurl提供了多种... 目录1. libcurl 调试工具简介2. 输出请求消息使用 CURLOPT_VERBOSE使用 C

C++实现获取本机MAC地址与IP地址

《C++实现获取本机MAC地址与IP地址》这篇文章主要为大家详细介绍了C++实现获取本机MAC地址与IP地址的两种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实际工作中,项目上常常需要获取本机的IP地址和MAC地址,在此使用两种方案获取1.MFC中获取IP和MAC地址获取