Почему я не могу наследоваться интервалу в C++?

Я хотел бы смочь сделать это:

class myInt : public int
{

};

Почему не может я?

Почему я хотел бы? Более сильный ввод. Например, я мог определить два класса intA и intB, которые позволяют мне сделать intA + intA или intB + intB, но нет intA + intB.

"Ints не являются классами". И что?

"Ints не имеют никаких членских данных". Да они делают, у них есть 32 бита, или что бы то ни было.

"Ints не имеют никаких функций членства". Ну, у них есть целый набор операторов как + и -.

57
задан Keith Pinson 12 February 2013 в 20:52
поделиться

17 ответов

Если вы используете 0,9 бета-версия Cocos2D имеет действительно простое обнаружение касания для кокозонов. Настоящая красота этого нового обнаружения состоит в том, что она хорошо справляется с несколькими сенсорными отслеживанием.

Пример этого можно найти здесь

http://code.google.com/p/cocos2d-iphone/source/browse/#svn/trunk/tests/toushestest

-121--2790240-

Комментарий Нила довольно точно. Bjarne упомянул рассмотрение и отклонение этой точной возможности 1 :

Синтаксис инициализатора используется для незаконно для встроенных типов. Позволять это, я представил понятие, которое Встроенные типы имеют конструкторы и деструкторы. Например:

 int a (1);  // Ошибка до 2,1, теперь инициализирует A до 1
 

Я считал, что расширяя это понятие Разрешить вывод от встроенных классов и явная декларация встроенного Операторы для встроенных типов. Тем не мение, Я сдержал себя.

позволяет вывод от int не на самом деле дать программист C ++ что-нибудь значительно новое по сравнению с Участник INT . Это в первую очередь, потому что int не имеет любые виртуальные функции для производных класс для переопределения. Более серьезно Хотя правила конверсии C так хаотичный, который притворяется, что int , Короткое и т. Д., Хорошо себя ведет Обычные классы не собираются работать. Они либо C совместимы, либо они подчиняться относительно хорошо поведенскому C ++ Правила для классов, но не обоих.

Насколько комментарий производительность оправдывает, не делая int класс, он (по крайней мере, в основном) false. В SmallTalk все виды являются классами - но почти все реализации SmallTalk имеют оптимизацию, поэтому реализация может быть по существу идентична, как вы сделаете работу не класса. Например, класс SmallInteger представляет собой 15-битное целое число, а сообщение «+» жестко закодируется в виртуальную машину, поэтому, даже если вы можете получить от SmallInteger, он все еще дает производительность, аналогичную встроенному типу ( Хотя SmallTalk достаточно отличается от C ++, что прямые сравнения производительности сложно и вряд ли значит значит много).

Один бит, который «потрачен» в реализации SmallTalk от SmandInteger (причина, по которой оно только представляет 15 бит вместо 16), вероятно, не потребуется в C или C ++. SmallTalk немного похоже на Java - когда вы «определяете объект», вы действительно просто определяете указатель на объект, и вам приходится динамически выделять объект для него, чтобы указать на. То, что вы манипулируете, проходите к функции в качестве параметра и т. Д. Всегда только указатель, а не сам объект.

Это , как меньшинтер реализован, хотя - в его случае они помещают целочисленное значение непосредственно в то, что обычно будет указателем. Чтобы различать меньшинцы и указателем, они заставляют выделять все объекты в даже границах байтов, поэтому LSB всегда ясен. SmallInteger всегда имеет набор LSB.

Однако большинство этого необходимо, однако, потому что SmallTalk динамически набирается - он должен быть в состоянии вывести тип, глядя на саму по себе значение, и SmallInteger в основном использует этот LSB в качестве типового тега. Учитывая, что C ++ статически набирается, никогда не нужно вывести тип из значения, поэтому вам, вероятно, не нужно «отпустить», чтобы он бил на тег.


1. В Дизайн и эволюция C ++ , §15.11.3.

82
ответ дан 24 November 2019 в 19:13
поделиться

Если я помню, это была главная или одна из - основные причины C ++ не считались настоящим ориентированным объектом языком. Java люди сказали бы: «В Яве все является объектом»;)

-1
ответ дан 24 November 2019 в 19:13
поделиться

Посмотрите на Albow , PGU или Ocemp .

-121--2943716-

Вы можете использовать WinINET API для достижения этой цели; WinINET определяет основные параметры настройки Интернета для большинства/многих приложений Windows и может использоваться для определения информации прокси. С учетом этого можно создать прокси, который отклоняет все запросы, кроме сообщений.

-121--4904051-

В C++ встроенные типы не являются классами.

3
ответ дан 24 November 2019 в 19:13
поделиться

Более общее, чем тот факт, что «int представляет собой примитив»: INT INT - это Scalar , в то время как классы агрегат типы. Скаляр - это атомное значение, а совокупность - это что-то с членами. Наследование (по крайней мере, так как он существует в C ++), имеет смысл для агрегатального типа, потому что вы не можете добавить членов или методов скаляров - по определению, у них нет ни каких-либо членов.

0
ответ дан 24 November 2019 в 19:13
поделиться

То, что другие сказали, является правдой ... INT является примитивным в C ++ (очень похоже на C #). Тем не менее, вы можете добиться того, что вы хотели, просто строительство класса вокруг INT :

class MyInt
{
private:
   int mInt;

public:
   explicit MyInt(int in) { mInt = in; }
   // Getters/setters etc
};

Вы можете унаследовать от того, что все, что вы веселитесь.

5
ответ дан 24 November 2019 в 19:13
поделиться

Что значит унаследовать от INT?

«int» не имеет функций члена; Он не имеет данных члена, это на 32 (или 64) битовое представление в памяти. У него нет собственного VTable. Все, что он «имеет» (оно на самом деле даже не владеет) - некоторые операторы, такие как + - / *, которые действительно более глобальные функции, чем функции членов.

1
ответ дан 24 November 2019 в 19:13
поделиться

Сильная набрав INTS (и поплавок и т. Д.) В C ++

Скотт Мейер ( Эффективное C ++ имеет очень эффективное и мощное решение вашей проблемы выполнения сильных типов базовых типов в C ++ , И это работает так:

Сильная набравка - это проблема, которая может быть адресована и оценена при компиляции , что означает, что вы можете использовать ординалы (слабые набравшими) для нескольких типов во время выполнения Развернутые приложения и используют специальную фазу компиляции для утилизации неподходящих комбинаций типов при компиляционном времени.

#ifdef STRONG_TYPE_COMPILE
typedef time Time
typedef distance Distance
typedef velocity Velocity
#else
typedef time float
typedef distance float
typedef velocity float
#endif

Вы тогда определяете ваше время , Масса , Расстояние Быть классами со всеми (и только) соответствующими операторами, перегруженными в соответствующие операции. В псевдокоде:

class Time {
  public: 
  float value;
  Time operator +(Time b) {self.value + b.value;}
  Time operator -(Time b) {self.value - b.value;}
  // don't define Time*Time, Time/Time etc.
  Time operator *(float b) {self.value * b;}
  Time operator /(float b) {self.value / b;}
}

class Distance {
  public:
  float value;
  Distance operator +(Distance b) {self.value + b.value;}
  // also -, but not * or /
  Velocity operator /(Time b) {Velocity( self.value / b.value )}
}

class Velocity {
  public:
  float value;
  // appropriate operators
  Velocity(float a) : value(a) {}
}

Как только это сделано, ваш компилятор скажет вам какие-либо места, которые вы нарушили правила, закодированные в вышеуказанных классах.

Я позволю вам выработать остальные детали самостоятельно или купить книгу.

9
ответ дан 24 November 2019 в 19:13
поделиться

Никто не упомянул, что C ++ был разработан, чтобы иметь (в основном) обратной совместимости с C, чтобы ослабить путь обновления для кодов C, следовательно, struct Уровень по умолчанию для всех участников Public и т. Д.

Иметь INT в качестве базового класса, в качестве базового класса, который вы могли бы переопределить, будет в основном усложнять это правило, и сделать реализацию компилятора адскую, и если вы хотите, чтобы существующие кодировщики и поставщики компилятора поддержали ваш язык Fledling вероятно, не стоит усилий.

4
ответ дан 24 November 2019 в 19:13
поделиться

Ну, вам действительно не нужно наследовать все, что не имеет никаких функций виртуальных участников. Так что даже если INT были классом, не будет плюс над композицией.

Так сказать, виртуальное наследование является единственной реальной причиной, по которой вам нужно наследование на наследство; Все остальное просто спасает вас массы ввода времени. И я не думаю, что int класс / тип с виртуальными участниками будет самым важным представителем в мире C ++. По крайней мере, для вас каждый день int .

2
ответ дан 24 November 2019 в 19:13
поделиться

Поскольку int - это родной тип, а не класс

Редактировать: перемещение моих комментариев в мой ответ.

Это происходит от наследия C и что именно, примитивы представляют собой. Примитив в C ++ - это просто набор байтов, которые мало значат, за исключением компилятора. Класс, с другой стороны, имеет функциональную таблицу, и как только вы начнете идти по поводу наследства и виртуального наследования, то у вас есть VTable. Никто из этого не присутствует в приведенном в примибильном, и, делая его присутствующим, что вы бы а) разбили много C-кода, который предполагает, что INT - это только 8 байтов, а B) Сделать программы намного больше памяти.

Подумайте об этом другим способом. INT / FLOAT / CHAR не имеет никаких данных или методов данных. Подумайте о примитивах как кварках - они являются строительными блоками, которые вы не можете подразделить, вы используете их, чтобы сделать более крупные вещи (извинения, если моя аналогия немного выключена, я не знаю достаточно физики частиц)

10
ответ дан 24 November 2019 в 19:13
поделиться

Если OP действительно хочет понять, почему C ++ - это способ, то он должен получить копию книги STROUSTUP «Дизайн и эволюцию C ++». Это объясняет обоснование этого и многих других проектных решений в первые дни C ++.

14
ответ дан 24 November 2019 в 19:13
поделиться

int - порядковый тип, а не класс. Почему вы хотите?

Если вам нужно добавить функциональность на «int», рассмотрите возможность построения совокупного класса, в котором есть целочисленное поле, а также методы, которые подвергают любые дополнительные возможности, которые вам требуют.

Обновление

@OP «ints не классы» так?

Наследование , полиморфизм и инкапсуляция являются ключевыми камнями объектно-ориентированного дизайна . Ни одно из этих вещей не распространяется на порядковые типы. Вы не можете наследовать от INT, потому что это просто кучка байтов и не имеет кода.

Ints, Chars и другие порядковые типы не имеют таблиц метода , поэтому нет способа добавлять методы или переопределить их, что на самом деле является сердцем наследования.

53
ответ дан 24 November 2019 в 19:13
поделиться

Как и другие мои слова, не может быть сделано, так как int - это примитивный тип.

Я понимаю мотивацию, однако, если это для более сильного набора текста. Для C++0x даже было предложено, чтобы для этого было достаточно специального типа typedef (но это было отклонено?).

Возможно, чего-то можно было бы добиться, если бы вы сами предоставили базовую обертку. Например, что-то вроде следующего, что, надеюсь, легально использует любопытно повторяющиеся шаблоны, и требует только получения класса и предоставления подходящего конструктора:

template <class Child, class T>
class Wrapper
{
    T n;
public:
    Wrapper(T n = T()): n(n) {}
    T& value() { return n; }
    T value() const { return n; }
    Child operator+= (Wrapper other) { return Child(n += other.n); }
    //... many other operators
};

template <class Child, class T>
Child operator+(Wrapper<Child, T> lhv, Wrapper<Child, T> rhv)
{
    return Wrapper<Child, T>(lhv) += rhv;
}

//Make two different kinds of "int"'s

struct IntA : public Wrapper<IntA, int>
{
    IntA(int n = 0): Wrapper<IntA, int>(n) {}
};

struct IntB : public Wrapper<IntB, int>
{
    IntB(int n = 0): Wrapper<IntB, int>(n) {}
};

#include <iostream>

int main()
{
    IntA a1 = 1, a2 = 2, a3;
    IntB b1 = 1, b2 = 2, b3;
    a3 = a1 + a2;
    b3 = b1 + b2;
    //a1 + b1;  //bingo
    //a1 = b1; //bingo
    a1 += a2;

    std::cout << a1.value() << ' ' << b3.value() << '\n';
}

Но если вы воспользуетесь советом просто определить новый тип и перегрузить операторы, вы можете взглянуть на Boost.Operators

3
ответ дан 24 November 2019 в 19:13
поделиться

Почему я хочу? Сильнее печатать. Например, я мог бы определить два класса Inta и INTB, что позвольте мне сделать Inta + Inta или INTB + INTB, но не Inta + Intb.

Это не имеет смысла. Вы можете сделать все это без наследства от чего-либо. (А с другой стороны, я не вижу, как вы могли бы достичь его, используя наследство.) Например,

class SpecialInt {
 ...
};
SpecialInt operator+ (const SpecialInt& lhs, const SpecialInt& rhs) {
  ...
}

Заполните пробелы, и у вас есть тип, который решает вашу проблему. Вы можете сделать Specialint + Specialint или int + int , но Специализируется + INT не будет компитен, точно так, как вы хотели.

С другой стороны, если мы притворяемся, что наследование от INT было законно, а наше специальнику , полученных из int , то специальностью + INT будет компилируйте. Наследование приведет к точной проблеме, которую вы хотите избежать. Не Унаследование легко избежать проблемы.

«INT не имеет никаких функций-членов». Ну, у них есть целый кучу операторов, таких как + и -.

Это не являются функциями члена, хотя.

25
ответ дан 24 November 2019 в 19:13
поделиться

Это связано с тем, как элементы хранятся в памяти. INT в C ++ является неотъемлемым типом, как упомянуто в другом месте и составляет всего 32 или 64 бита (слово) в памяти. Однако объект хранится по-разному в памяти. Обычно он хранится на куче, и он имеет функциональность, связанные с полиморфизмом.

Я не знаю, как это объяснить это лучше. Как бы вы наследовали от номера 4?

-3
ответ дан 24 November 2019 в 19:13
поделиться

Почему вы не можете наследовать от INT, даже если вы можете захотеть?

производительность

Нет функциональной причины, по которой вы не должны быть в состоянии (на произвольном языке) наследовать от порядковых типов, таких как Int или char, или char * и т. Д. Некоторые языки, такие как Java и Objective-C, фактически предоставляют версии базового типа класса / объекта (в штучной упаковке), чтобы удовлетворить эту потребность (а также для решения некоторых других неприятных последствий Порядковые типы не являются объектами):

language     ordinal type boxed type, 
c++          int          ?
java         int          Integer
objective-c  int          NSNumber

Но даже Java и Objective-C сохраняют свои порядковые типы для использования ... Почему?

Простые причины являются производительность и потребление памяти. Как правило, порядковый тип обычно можно построить и передаваться по значению всего за один или два инструкции x86 и только потребляет несколько байтов в худшем случае. Класс обычно не может - это часто использует 2 раза или более как большая память, а манипулирование его значением может принимать много сотен циклов.

Это означает, что программисты, которые понимают, что это, как правило, используют порядковые типы для реализации выполнения или программного обеспечения для использования производительности или использования памяти, и потребуют, чтобы разработчики языка поддерживают базовые типы.

Следует отметить, что немногие языки не имеют порядковых типов, в частности, динамические языки, такие как Perl , который почти полностью зависит от вариационного типа, что является чем-то еще, и акции некоторые из накладных расходов классов.

-3
ответ дан 24 November 2019 в 19:13
поделиться

Вы можете получить то, что хотите, с помощью строгих typedefs. См. BOOST_STRONG_TYPEDEF

1
ответ дан 24 November 2019 в 19:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: