久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

為什么不應該從 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 入門)
主站蜘蛛池模板: 在线观看国产三级 | 久久精品国产一区老色匹 | 伊人精品久久久久77777 | 一区二区三区视频在线观看 | www.日韩系列 | 成年人在线观看 | 国产伦精品一区二区三区照片91 | 天天干天天干 | 国产极品91 | 国内精品久久久久久 | 国产一区 | 99综合在线 | 国产午夜亚洲精品不卡 | 日韩欧美视频网站 | av色在线| 国产精久久久 | 亚洲性视频| 91精品国产综合久久小仙女图片 | 日韩精品在线看 | 国产精品91久久久久久 | 欧美自拍第一页 | 日韩高清在线 | 午夜在线精品 | 在线观看免费毛片 | 国产欧美一区二区三区在线看 | 九九亚洲 | 久久精品色视频 | 国产成人影院 | 成人三级网址 | 一级黄色片毛片 | 欧美精品在线一区二区三区 | 午夜精品一区二区三区在线观看 | 国产精品久久久久久久久免费软件 | 99热热精品 | 国产欧美视频一区二区 | 欧美视频免费在线观看 | 日本在线视频一区二区 | 久久r久久| 亚洲国产一区二区在线 | 黄色成人在线观看 | 国产一区二区精品在线 |