pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

為什么不應該從 c++ std 字符串類派生?

Why should one not derive from c++ std string class?(為什么不應該從 c++ std 字符串類派生?)
本文介紹了為什么不應該從 c++ std 字符串類派生?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我想問一下 Effective C++ 中提出的一個具體觀點.

I wanted to ask about a specific point made in Effective C++.

它說:

如果一個類需要像一個多態類一樣運行,那么析構函數應該是虛擬的.它還進一步補充說,由于 std::string 沒有虛擬析構函數,因此永遠不應從中派生.另外 std::string 甚至都沒有被設計為基類,忘記多態基類.

A destructor should be made virtual if a class needs to act like a polymorphic class. It further adds that since std::string does not have a virtual destructor, one should never derive from it. Also std::string is not even designed to be a base class, forget polymorphic base class.

我不明白要成為基類(不是多態類)的類具體需要什么?

I do not understand what specifically is required in a class to be eligible for being a base class (not a polymorphic one)?

我不應該從 std::string 類派生的唯一原因是它沒有虛擬析構函數嗎?出于可重用性的目的,可以定義一個基類,并且可以從它繼承多個派生類.那么是什么讓 std::string 甚至沒有資格作為基類?

Is the only reason that I should not derive from std::string class is it does not have a virtual destructor? For reusability purpose a base class can be defined and multiple derived class can inherit from it. So what makes std::string not even eligible as a base class?

另外,如果有一個純粹為了可重用性目的而定義的基類,并且有許多派生類型,有沒有辦法阻止客戶端執行 Base* p = new Derived() 因為類不是要多態使用嗎?

Also, if there is a base class purely defined for reusability purpose and there are many derived types, is there any way to prevent client from doing Base* p = new Derived() because the classes are not meant to be used polymorphically?

推薦答案

我認為這個聲明反映了這里的混亂(強調我的):

I think this statement reflects the confusion here (emphasis mine):

我不明白在類中有什么具體要求才有資格成為基類(不是多態類)?

I do not understand what specifically is required in a class to be eligible for being a base clas (not a polymorphic one)?

在慣用的 C++ 中,從類派生有兩種用途:

In idiomatic C++, there are two uses for deriving from a class:

  • 私有繼承,用于使用模板的混合和面向方面的編程.
  • public 繼承,僅用于多態情況.編輯:好的,我想這也可以用在一些混合場景中——比如 boost::iterator_facade——當 CRTP 正在使用中.
  • private inheritance, used for mixins and aspect oriented programming using templates.
  • public inheritance, used for polymorphic situations only. EDIT: Okay, I guess this could be used in a few mixin scenarios too -- such as boost::iterator_facade -- which show up when the CRTP is in use.

如果你不想做一些多態的事情,絕對沒有理由在 C++ 中公開派生一個類.該語言帶有免費函數作為該語言的標準特性,而免費函數正是您在這里應該使用的.

There is absolutely no reason to publicly derive a class in C++ if you're not trying to do something polymorphic. The language comes with free functions as a standard feature of the language, and free functions are what you should be using here.

這樣想——你真的想僅僅因為你想添加一些方法就強迫你的代碼的客戶端轉換為使用一些專有的字符串類嗎?因為與 Java 或 C#(或大多數類似的面向對象語言)不同,當您在 C++ 中派生類時,基類的大多數用戶都需要了解這種更改.在Java/C#中,類通常是通過引用來訪問的,類似于C++的指針.因此,涉及到一定程度的間接性,它將您的類的客戶端解耦,允許您在其他客戶端不知道的情況下替換派生類.

Think of it this way -- do you really want to force clients of your code to convert to using some proprietary string class simply because you want to tack on a few methods? Because unlike in Java or C# (or most similar object oriented languages), when you derive a class in C++ most users of the base class need to know about that kind of a change. In Java/C#, classes are usually accessed through references, which are similar to C++'s pointers. Therefore, there's a level of indirection involved which decouples the clients of your class, allowing you to substitute a derived class without other clients knowing.

然而,在 C++ 中,類是值類型——與大多數其他面向對象語言不同.看到這一點的最簡單方法是所謂的切片問題.基本上,請考慮:

However, in C++, classes are value types -- unlike in most other OO languages. The easiest way to see this is what's known as the slicing problem. Basically, consider:

int StringToNumber(std::string copyMeByValue)
{
    std::istringstream converter(copyMeByValue);
    int result;
    if (converter >> result)
    {
        return result;
    }
    throw std::logic_error("That is not a number.");
}

如果您將自己的字符串傳遞給此方法,將調用 std::string 的復制構造函數來進行復制,而不是派生對象的復制構造函數 -- 不管 std::string 的子類是什么.這可能會導致您的方法與附加到字符串的任何內容之間出現不一致.函數 StringToNumber 不能簡單地接受任何你的派生對象并復制它,僅僅因為你的派生對象可能具有與 std::string 不同的大小——但是這個函數被編譯為只為自動存儲中的 std::string 保留空間.在 Java 和 C# 中,這不是問題,因為唯一涉及的自動存儲是引用類型,并且引用的大小始終相同.在 C++ 中不是這樣.

If you pass your own string to this method, the copy constructor for std::string will be called to make a copy, not the copy constructor for your derived object -- no matter what child class of std::string is passed. This can lead to inconsistency between your methods and anything attached to the string. The function StringToNumber cannot simply take whatever your derived object is and copy that, simply because your derived object probably has a different size than a std::string -- but this function was compiled to reserve only the space for a std::string in automatic storage. In Java and C# this is not a problem because the only thing like automatic storage involved are reference types, and the references are always the same size. Not so in C++.

長話短說——不要使用繼承來添加 C++ 中的方法.這不是慣用的,會導致語言出現問題.盡可能使用非友元、非成員函數,然后是組合.除非您是模板元編程或想要多態行為,否則不要使用繼承.有關詳細信息,請參閱 Scott Meyers 的 Effective C++ 條目23:優先使用非成員非友元函數而不是成員函數.

Long story short -- don't use inheritance to tack on methods in C++. That's not idiomatic and results in problems with the language. Use non-friend, non-member functions where possible, followed by composition. Don't use inheritance unless you're template metaprogramming or want polymorphic behavior. For more information, see Scott Meyers' Effective C++ Item 23: Prefer non-member non-friend functions to member functions.

這是一個更完整的示例,顯示了切片問題.您可以在 codepad.org

Here's a more complete example showing the slicing problem. You can see it's output on codepad.org

#include <ostream>
#include <iomanip>

struct Base
{
    int aMemberForASize;
    Base() { std::cout << "Constructing a base." << std::endl; }
    Base(const Base&) { std::cout << "Copying a base." << std::endl; }
    ~Base() { std::cout << "Destroying a base." << std::endl; }
};

struct Derived : public Base
{
    int aMemberThatMakesMeBiggerThanBase;
    Derived() { std::cout << "Constructing a derived." << std::endl; }
    Derived(const Derived&) : Base() { std::cout << "Copying a derived." << std::endl; }
    ~Derived() { std::cout << "Destroying a derived." << std::endl; }
};

int SomeThirdPartyMethod(Base /* SomeBase */)
{
    return 42;
}

int main()
{
    Derived derivedObject;
    {
        //Scope to show the copy behavior of copying a derived.
        Derived aCopy(derivedObject);
    }
    SomeThirdPartyMethod(derivedObject);
}

這篇關于為什么不應該從 c++ std 字符串類派生?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

boost_1_60_0 .zip installation in windows(Windows 中的 boost_1_60_0 .zip 安裝)
How do I get console output in C++ with a Windows program?(如何使用 Windows 程序在 C++ 中獲得控制臺輸出?)
How do I calculate the week number given a date?(如何計算給定日期的周數?)
OpenCV with Network Cameras(帶有網絡攝像機的 OpenCV)
Export all symbols when creating a DLL(創建 DLL 時導出所有符號)
Getting started with OpenCV 2.4 and MinGW on Windows 7(Windows 7 上的 OpenCV 2.4 和 MinGW 入門)
主站蜘蛛池模板: 邢台人才网_邢台招聘网_邢台123招聘【智达人才网】 | 精密五金冲压件_深圳五金冲压厂_钣金加工厂_五金模具加工-诚瑞丰科技股份有限公司 | 东风体检车厂家_公共卫生体检车_医院体检车_移动体检车-锦沅科贸 | 产业规划_产业园区规划-产业投资选址及规划招商托管一体化服务商-中机院产业园区规划网 | 金属切削液-脱水防锈油-电火花机油-抗磨液压油-深圳市雨辰宏业科技发展有限公司 | 提升海外网站流量,增加国外网站访客UV,定制海外IP-访客王 | 电动高尔夫球车|电动观光车|电动巡逻车|电动越野车厂家-绿友机械集团股份有限公司 | 工业洗衣机_工业洗涤设备_上海力净工业洗衣机厂家-洗涤设备首页 bkzzy在职研究生网 - 在职研究生招生信息咨询平台 | 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 筒瓦厂家-仿古瓦-寺庙-古建琉璃瓦-宜兴市古典园林建筑陶瓷厂有限公司 | 深圳美安可自动化设备有限公司,喷码机,定制喷码机,二维码喷码机,深圳喷码机,纸箱喷码机,东莞喷码机 UV喷码机,日期喷码机,鸡蛋喷码机,管芯喷码机,管内壁喷码机,喷码机厂家 | 神超官网_焊接圆锯片_高速钢锯片_硬质合金锯片_浙江神超锯业制造有限公司 | 合肥办公室装修 - 合肥工装公司 - 天思装饰 | 硅PU球场、篮球场地面施工「水性、环保、弹性」硅PU材料生产厂家-广东中星体育公司 | 成都竞价托管_抖音代运营_网站建设_成都SEM外包-成都智网创联网络科技有限公司 | led全彩屏-室内|学校|展厅|p3|户外|会议室|圆柱|p2.5LED显示屏-LED显示屏价格-LED互动地砖屏_蕙宇屏科技 | 酒精检测棒,数显温湿度计,酒安酒精测试仪,酒精检测仪,呼气式酒精检测仪-郑州欧诺仪器有限公司 | 开平机_纵剪机厂家_开平机生产厂家|诚信互赢-泰安瑞烨精工机械制造有限公司 | 【MBA备考网】-2024年工商管理硕士MBA院校/报考条件/培训/考试科目/提前面试/考试/学费-MBA备考网 | 中开泵,中开泵厂家,双吸中开泵-山东博二泵业有限公司 | 山东PE给水管厂家,山东双壁波纹管,山东钢带增强波纹管,山东PE穿线管,山东PE农田灌溉管,山东MPP电力保护套管-山东德诺塑业有限公司 | 翰香原枣子坊加盟费多少钱-正宗枣核糕配方培训利润高飘香 | 车牌识别道闸_停车场收费系统_人脸识别考勤机_速通门闸机_充电桩厂家_中全清茂官网 | 玉米深加工设备-玉米深加工机械-新型玉米工机械生产厂家-河南粮院机械制造有限公司 | 沟盖板_复合沟盖板厂_电力盖板_树脂雨水篦子-淄博拜斯特 | B2B网站_B2B免费发布信息网站_B2B企业贸易平台 - 企资网 | 东莞画册设计_logo/vi设计_品牌包装设计 - 华略品牌设计公司 | 耐火砖厂家,异形耐火砖-山东瑞耐耐火材料厂 | 办公室家具_板式办公家具定制厂家-FMARTS福玛仕办公家具 | 衢州装饰公司|装潢公司|办公楼装修|排屋装修|别墅装修-衢州佳盛装饰 | 送料机_高速冲床送料机_NC伺服滚轮送料机厂家-东莞市久谐自动化设备有限公司 | 超声波成孔成槽质量检测仪-压浆机-桥梁预应力智能张拉设备-上海硕冠检测设备有限公司 | 精密钢管,冷拔精密无缝钢管,精密钢管厂,精密钢管制造厂家,精密钢管生产厂家,山东精密钢管厂家 | 南京租车,南京汽车租赁,南京包车,南京会议租车-南京七熹租车 | 东莞市踏板石餐饮管理有限公司_正宗桂林米粉_正宗桂林米粉加盟_桂林米粉加盟费-东莞市棒子桂林米粉 | 赛默飞Thermo veritiproPCR仪|ProFlex3 x 32PCR系统|Countess3细胞计数仪|371|3111二氧化碳培养箱|Mirco17R|Mirco21R离心机|仟诺生物 | 存包柜厂家_电子存包柜_超市存包柜_超市电子存包柜_自动存包柜-洛阳中星 | 动力配电箱-不锈钢配电箱-高压开关柜-重庆宇轩机电设备有限公司 聚天冬氨酸,亚氨基二琥珀酸四钠,PASP,IDS - 远联化工 | NM-02立式吸污机_ZHCS-02软轴刷_二合一吸刷软轴刷-厦门地坤科技有限公司 | 两头忙,井下装载机,伸缩臂装载机,30装载机/铲车,50装载机/铲车厂家_价格-莱州巨浪机械有限公司 | 日本SMC气缸接头-速度控制阀-日本三菱伺服电机-苏州禾力自动化科技有限公司 |