OOP (C++). Манипулирование объектами без ссылок.
1698
7
Долго думал, как озаглавить топик, никак не мог сформулировать...

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

Пример:
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;

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

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



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

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

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

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

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



пример:



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.

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

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

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