Действительно ли встроенные виртуальные функции не имеют смысла? - PullRequest
159 голосов
/ 09 апреля 2009

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

Я думал, что встроенные виртуальные функции могут пригодиться в сценариях, где функции вызываются непосредственно для объектов. Но мне пришёл в голову контраргумент: зачем нужно определять виртуальные, а затем использовать объекты для вызова методов?

Не лучше ли использовать встроенные виртуальные функции, поскольку они почти никогда не расширяются?

Фрагмент кода, который я использовал для анализа:

class Temp
{
public:

    virtual ~Temp()
    {
    }
    virtual void myVirtualFunction() const
    {
        cout<<"Temp::myVirtualFunction"<<endl;
    }

};

class TempDerived : public Temp
{
public:

    void myVirtualFunction() const
    {
        cout<<"TempDerived::myVirtualFunction"<<endl;
    }

};

int main(void) 
{
    TempDerived aDerivedObj;
    //Compiler thinks it's safe to expand the virtual functions
    aDerivedObj.myVirtualFunction();

    //type of object Temp points to is always known;
    //does compiler still expand virtual functions?
    //I doubt compiler would be this much intelligent!
    Temp* pTemp = &aDerivedObj;
    pTemp->myVirtualFunction();

    return 0;
}

Ответы [ 12 ]

0 голосов
/ 26 апреля 2012

Имеет смысл создавать виртуальные функции и затем вызывать их для объектов, а не для ссылок или указателей. Скотт Мейер рекомендует в своей книге «эффективный с ++» никогда не переопределять унаследованную не виртуальную функцию. Это имеет смысл, потому что когда вы создаете класс с не-виртуальной функцией и переопределяете функцию в производном классе, вы можете быть уверены, что используете его правильно самостоятельно, но вы не можете быть уверены, что другие будут использовать его правильно. Кроме того, вы можете позже использовать его неправильно. Итак, если вы создаете функцию в базовом классе и хотите, чтобы она была перенаправляемой, вы должны сделать ее виртуальной. Если имеет смысл создавать виртуальные функции и вызывать их для объектов, также имеет смысл их встроить.

0 голосов
/ 09 апреля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...