вернулся 1 статус выхода, c program [duplicate]

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

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

Не виртуальный метод & rArr; статическая привязка

Следующий код преднамеренно неправильный & rdquo ;. Он не объявляет метод value как virtual и поэтому создает непреднамеренное & ldquo; wrong & rdquo; результат, а именно 0:

#include <iostream>
using namespace std;

class Expression
{
public:
    auto value() const
        -> double
    { return 0.0; }         // This should never be invoked, really.
};

class Number
    : public Expression
{
private:
    double  number_;

public:
    auto value() const
        -> double
    { return number_; }     // This is OK.

    Number( double const number )
        : Expression()
        , number_( number )
    {}
};

class Sum
    : public Expression
{
private:
    Expression const*   a_;
    Expression const*   b_;

public:
    auto value() const
        -> double
    { return a_->value() + b_->value(); }       // Uhm, bad! Very bad!

    Sum( Expression const* const a, Expression const* const b )
        : Expression()
        , a_( a )
        , b_( b )
    {}
};

auto main() -> int
{
    Number const    a( 3.14 );
    Number const    b( 2.72 );
    Number const    c( 1.0 );

    Sum const       sum_ab( &a, &b );
    Sum const       sum( &sum_ab, &c );

    cout << sum.value() << endl;
}

В строке, прокомментированной как & ldquo; bad & rdquo; вызывается метод Expression::value, потому что статически известный тип (тип, известный во время компиляции) является Expression, а метод value не является виртуальным.

Виртуальный метод & rArr; динамическое связывание.

Объявление value как virtual в статически известном типе Expression гарантирует, что каждый вызов будет проверять, каков фактический тип объекта, и вызвать соответствующую реализацию value для этого динамического типа:

#include <iostream>
using namespace std;

class Expression
{
public:
    virtual
    auto value() const -> double
        = 0;
};

class Number
    : public Expression
{
private:
    double  number_;

public:
    auto value() const -> double
        override
    { return number_; }

    Number( double const number )
        : Expression()
        , number_( number )
    {}
};

class Sum
    : public Expression
{
private:
    Expression const*   a_;
    Expression const*   b_;

public:
    auto value() const -> double
        override
    { return a_->value() + b_->value(); }    // Dynamic binding, OK!

    Sum( Expression const* const a, Expression const* const b )
        : Expression()
        , a_( a )
        , b_( b )
    {}
};

auto main() -> int
{
    Number const    a( 3.14 );
    Number const    b( 2.72 );
    Number const    c( 1.0 );

    Sum const       sum_ab( &a, &b );
    Sum const       sum( &sum_ab, &c );

    cout << sum.value() << endl;
}

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

Соответствующая реализация является той, которая относится к наиболее определенному (самому производному) классу.

Обратите внимание, что реализации методов в производных классах здесь не отмечены virtual, но вместо этого отмечены override. Они могут быть отмечены virtual, но они автоматически становятся виртуальными. Ключевое слово override гарантирует, что если в каком-либо базовом классе есть not такой виртуальный метод, вы получите ошибку (что желательно).

Уродство делать это без виртуальных методов

Без virtual нужно было бы реализовать некоторую Do It Yourself версию динамической привязки. Это обычно подразумевает небезопасное ручное понижение, сложность и многословие.

Для случая одной функции, как здесь, достаточно сохранить указатель на функцию в объекте и вызвать через этот указатель функции, но даже это связано с некоторыми небезопасными понижениями, сложностью и многословием, а именно:

#include <iostream>
using namespace std;

class Expression
{
protected:
    typedef auto Value_func( Expression const* ) -> double;

    Value_func* value_func_;

public:
    auto value() const
        -> double
    { return value_func_( this ); }

    Expression(): value_func_( nullptr ) {}     // Like a pure virtual.
};

class Number
    : public Expression
{
private:
    double  number_;

    static
    auto specific_value_func( Expression const* expr )
        -> double
    { return static_cast<Number const*>( expr )->number_; }

public:
    Number( double const number )
        : Expression()
        , number_( number )
    { value_func_ = &Number::specific_value_func; }
};

class Sum
    : public Expression
{
private:
    Expression const*   a_;
    Expression const*   b_;

    static
    auto specific_value_func( Expression const* expr )
        -> double
    {
        auto const p_self  = static_cast<Sum const*>( expr );
        return p_self->a_->value() + p_self->b_->value();
    }

public:
    Sum( Expression const* const a, Expression const* const b )
        : Expression()
        , a_( a )
        , b_( b )
    { value_func_ = &Sum::specific_value_func; }
};


auto main() -> int
{
    Number const    a( 3.14 );
    Number const    b( 2.72 );
    Number const    c( 1.0 );

    Sum const       sum_ab( &a, &b );
    Sum const       sum( &sum_ab, &c );

    cout << sum.value() << endl;
}

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

12
задан Gilles 30 October 2012 в 16:28
поделиться

4 ответа

unistd.h и fork являются частью стандарта POSIX .

Похоже, вы используете gcc как часть MinGW

Похоже, вы используете gcc как часть MinGW

g1], который предоставляет заголовок unistd.h, но не выполняет такие функции, как fork. Cygwin делает реализацию реализаций таких функций, как fork.

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

31
ответ дан strcat 26 August 2018 в 10:15
поделиться

Я думаю, что вам нужно сделать следующее:

pid_t pid = fork();

Чтобы узнать больше о Linux API, перейдите на эту страницу онлайн-руководства или даже зайдите в свою терминал прямо сейчас и введите

man fork

Удачи!

0
ответ дан 2fewChars 26 August 2018 в 10:15
поделиться

Как вы уже отметили, fork () следует определить в unistd.h - по крайней мере, согласно страницам man, которые поставляются с Ubuntu 11.10. Минимальный:

#include <unistd.h>

int main( int argc, char* argv[])
{
    pid_t procID;

    procID = fork();
    return procID;
}

... строит без предупреждений в 11.10.

Говоря о том, какой дистрибутив UNIX / Linux вы используете? Например, я нашел несколько не замечательных функций, которые должны быть определены в заголовках Ubuntu 11.10, нет. Например:

// string.h
char* strtok_r( char* str, const char* delim, char** saveptr);
char* strdup( const char* const qString);

// stdio.h
int fileno( FILE* stream);

// time.h
int nanosleep( const struct timespec* req, struct timespec* rem);

// unistd.h
int getopt( int argc, char* const argv[], const char* optstring);
extern int opterr;
int usleep( unsigned int usec);

Пока они определены в вашей библиотеке C, это не будет большой проблемой. Просто определите свои собственные прототипы в заголовке совместимости и сообщите о стандартных проблемах с заголовками тем, кто поддерживает ваш дистрибутив ОС.

2
ответ дан Craig Mc 26 August 2018 в 10:15
поделиться

У вас есть #include <unistd.h>, где объявлено fork().

Итак, вам, вероятно, нужно сообщить системе, чтобы показать определения POSIX, прежде чем включать заголовки системы:

#define _XOPEN_SOURCE 600

Вы можете использовать 700, если считаете, что ваша система в основном совместима с POSIX 2008 или даже 500 для более старой системы. Поскольку fork() существует бесконечно, он будет отображаться с любым из них.

Если вы компилируете с -std=c99 --pedantic, то все объявления для POSIX будут скрыты, если вы явно не запросите их как показано .

Вы также можете играть с _POSIX_C_SOURCE, но с помощью _XOPEN_SOURCE подразумеваются правильные соответствующие _POSIX_C_SOURCE_POSIX_SOURCE и т. д.).

4
ответ дан Jonathan Leffler 26 August 2018 в 10:15
поделиться
Другие вопросы по тегам:

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