0°C
завтра: −5°C
Погода в Перми
0°C
ночью−1°C
утром−5°C
завтра−5°C
Подробно
 63,58
−0.1456
Курс USD ЦБ РФна 11 декабря
63,5788
−0.1456
 70,39
−0.1166
Курс EUR ЦБ РФна 11 декабря
70,3881
−0.1166
PRM.Форум /Компьютеры Интернет Связь / Программирование /

OOP (C++). Манипулирование объектами без ссылок.

  • Долго думал, как озаглавить топик, никак не мог сформулировать...

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

    Пример:
    MFC-шный класс CString.
    Могу объявить любую функцию

    int f(CString str){
    // что угодно.
    }

    Аргумент в функции объявляется именно CString str, а не CString& str или CString* str.

    Соответственно, могу объявить функцию
    CString g(){ // не CString&, не CString*
    CString temp;
    // some manipulations with "temp"
    return temp;
    } - и все будет нормально.

    Как сделать такое с произвольным классом?

    Когда проснулся, тогда и "Доброе утро!"

  • посмотри литературу : парадигма "конверт-письмо", подсчет ссылок.
    В общем, шаблоны тебе в руки - описать детально мне некогда...

  • Можешь объяснить зачем тебе это нужно? В принципе проблем нет кто тебе мешает завести произвольный класс скажем :
    class cTest
    {
    private:
    int iTest;
    public:
    cTest(){};
    };

    int Function(cTest test)
    {
    }


    Другой вопрос что подобное использование классов приводит к тому что ты не передаешь класс а создаешь его копию в стеке соответвенно это замедляет работу программы. Если тебя это не беспокоит то все что тебе нужно сделать чтобы подобный механизм работал безопасно заводи у класса для которого это нужно конструктор копировшик. Иначе будут проблеммы например такие:

    class cTest
    {
    private:
    void * m_pPointer;
    public:
    cTest(){ m_pPointer = new char[10000];}
    virtual ~cTest() {delete []m_pPointer;}
    }

    int Function(cTest test)
    {
    }

    void Funct()
    {
    cTest test;
    Function(test);
    }/// Вот здесь программа свалится с громкими матами.

    Чтобы избежать этого делаешь так:

    class cTest
    {
    private:
    void * m_pPointer;
    public:
    cTest(){ m_pPointer = new char[10000];}
    сTest(const cTest & test)
    {
    m_pPointer = new char[10000];
    memcpy(m_pPointer, test.m_pPointer, 10000);
    }
    virtual ~cTest() {delete []m_pPointer;}
    }

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

  • Передавать в функцию - это полбеды.
    Нужно еще и возвращать в качестве результата работы функции.

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

    class mTest{
    public:
    mTest operator+(mTest);
    mTest operator*(mTest);
    ....
    };

    Со ссылками есть свой косяк: для того, чтобы передать в качестве результата mTest*, нужно его создать внутри функции. А отслживать все это дело трудновато будет, алгоритм уж больно навороченный (всякие рекурсии с ветвлениями).

    2 Гость888:
    можно чуть подробнее? что-то не могу нарыть ничего...
    Хотя бы ссылку какую...

    Когда проснулся, тогда и "Доброе утро!"

  • Пока пришел к такому решению:

    class mTest{
    public:
    mTest* operator+(mTest&);
    mTest(const mTest*);
    ....
    };

    mTest* mTest::operator+(mTest& m){
    mTest* temp = new mTest();
    // .... addition
    return temp;
    }

    mTest::mTest(const mTest* m){
    // ... copying
    delete m;
    }

    В этом случае операция

    mTest m1, m2;
    mTest m3 = m1 + m2;

    нормально работает и память остается в целости.

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

    Когда проснулся, тогда и "Доброе утро!"

    Исправлено пользователем Поручик Голицын (20.05.04 17:09)

  • Если не очень лень, попробуй слазить вот сюда , там на Си-шном форуме народ тусуется подкованный. Глядишь, и расскажут, что почем.

  • правильно, что не нравится.



    а что мешает сделать, как уже сказали? т.е. правильно задать конструктор

    копирования и оператор присваивания. при этом тебе надо будет передавать

    в функции только ссылки, а возвращать иногда придется и объекты (я что-то не

    могу представить себе функцию, которой требовалось бы передавать именно

    объект, а не ссылку, может, кто подскажет?)



    пример:



    class TEST{

    private:

    int a;

    public:

    TEST(void){ a = 0;}

    TEST(int t){ a = t;}

    TEST(const TEST& t){ a = t.a;}

    ~TEST(void){;}



    TEST& operator=(const TEST& t){ a = t.a; return *this;}

    TEST& operator+=(const TEST& t){ a += t.a; return *this;}

    TEST operator+(const TEST& t) const { TEST tmp(*this); tmp += t; return tmp;}

    };



    т.е., у тебя есть конструктор копирования, и есть оператор присваивания.

    в "+=" и "=" ты передаешь и возвращаешь ссылку на объект,

    а в "+" передаешь ссылку, а возвращаешь объект (при этом неявно вызывается

    конструктор копирования). можно, конечно, сделать и так:



    TEST& operator+(const TEST &t){ return *this += t;}



    при этом не будет "лишнего" вызова конструктора, но появится побочный

    эффект: в вызове "+" будет изменятся первый аргумент:

    TEST t1, t2, t3;



    t3 = t1 + t2; // изменится t1.

  • Уже все разрулил на rsdn (ASGS, thnx за ссылку :pivo: :live:). Причем там просто помогли вспомнить то, что я и так знал :).

    И ну их на фиг, побочные эффекты... :). Тогда теряется смысл операции +, можно обойтись одним +=.
    Лучше сделать коротко и просто:

    TEST operator+(const TEST& t) const { return TEST(a + t.a);}

    Когда проснулся, тогда и "Доброе утро!"

Записей на странице:

Перейти в форум

Модератор: