OOP (C++). Манипулирование объектами без ссылок.
1701
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;
} - и все будет нормально.
Как сделать такое с произвольным классом?
В общем, суть вопроса:
как добиться того, чтобы с объектами можно было работать без помощи указателей и ссылок?
Пример:
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 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 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 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;
нормально работает и память остается в целости.
Но все же мне это не очень нравится, т.к. если не сделать присваивание, то ненужный объект (сумма) не будет удален.
ASGS
guru
Если не очень лень, попробуй слазить вот сюда , там на Си-шном форуме народ тусуется подкованный. Глядишь, и расскажут, что почем.
правильно, что не нравится.
а что мешает сделать, как уже сказали? т.е. правильно задать конструктор
копирования и оператор присваивания. при этом тебе надо будет передавать
в функции только ссылки, а возвращать иногда придется и объекты (я что-то не
могу представить себе функцию, которой требовалось бы передавать именно
объект, а не ссылку, может, кто подскажет?)
пример:
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.
а что мешает сделать, как уже сказали? т.е. правильно задать конструктор
копирования и оператор присваивания. при этом тебе надо будет передавать
в функции только ссылки, а возвращать иногда придется и объекты (я что-то не
могу представить себе функцию, которой требовалось бы передавать именно
объект, а не ссылку, может, кто подскажет?)
пример:
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.
Сейчас читают
обсуждение слайдов (часть 4)
261886
1000
Комментарии к конкурсу "Секси Бой МФ 2015!"
94074
588
Можно ли смотреть FULL HD видео с нетбука?
8565
31
Поручик Голицын
шатун сибирский обыкновенный
Уже все разрулил на rsdn (ASGS, thnx за ссылку ). Причем там просто помогли вспомнить то, что я и так знал :).
И ну их на фиг, побочные эффекты... :). Тогда теряется смысл операции +, можно обойтись одним +=.
Лучше сделать коротко и просто:
TEST operator+(const TEST& t) const { return TEST(a + t.a);}
И ну их на фиг, побочные эффекты... :). Тогда теряется смысл операции +, можно обойтись одним +=.
Лучше сделать коротко и просто:
TEST operator+(const TEST& t) const { return TEST(a + t.a);}