САБЖ сейчас занялся изучением классов. Вопрос такой МОжно ли как-то сделать класс, в котором будут паблик члены(переменные), но которые можно изменять только методами класса, а извне только читать ?
Сорри если ступил, но что мешает сделать Set метод закрытым ( т.е. писать ), а Get открытым ( т.е. читать ).
не знал спасибо я только разбираюсь с классами Еще вопрос В проекте по умолчанию соглашение о передаче аргументов _cdecl а можно ли как-то сделать так, чтобы в моем классе (в методах моего класса) по умолчанию соглашение было _fastcall ? т.е. чтобы не прописывать перед каждым методом _fastcall
А зачем такой подход собственно? Если для оптимизации, то компилятор обычно оптимизирует функции такого типа посредством inline: Код (Text): HWND TWindow::get_Handle () { return m_hWnd; } Кроме того, можно подстраховаться и таким образом: Код (Text): HWND TWindow::get_Handle () { ASSERT (::IsWindow (m_hWnd)); return m_hWnd; } В RELEASE-е всё это будет убрано и код получится как будто ты использовал член класса напрямую: Код (Text): TWindow win; HWND h = win.get_Handle (); // In RELEASE (with full optimization) Build turns into: TWindow win; HWND h = win.m_hWnd;
Если после создания объекта не требуется изменять данное-член, то можно сделать и так. Код (Text): class A{ public: A(int init_val = 0) : val(init_val) {} const int val; }; Хотя и в этом случае по хорошему не стоит его объявлять открытым, а стоит использовать int GetVal() {return val;} Код (Text): class A{ const int val; public: A(int init_val = 0) : val(init_val) {} int GetVal() {return val;} };
AsmGuru62 спасибо и еще вопрос Обычно когда все члены структуры мне нужно было сбросить в ноль, я юзал memset примерно так memset((void*)&mystruct, 0, sizeof(mystruct)); а как занулить все переменные класса? Если в классе около 100 переменных и еще методы. Не занулять же каждую по отдельности? Я так понимаю зануление нужно в конструкторе писать. Но мемсет не работает. Компилятор пишет illegal use of expression
Да, вроде компилится без ошибок Код (Text): #include <iostream> class A{ int val1; int val2; public: int GetVal1() {return val1;} int GetVal2() {return val2;} }; int main() { using std::cout; using std::endl; A a; memset((void*) &a, -1, sizeof(a)); cout << a.GetVal1() << endl; cout << a.GetVal2() << endl; return 0; }
Можно попробовать переопределить operator new для класса: Код (Text): class A { // ... void* operator new (size_t nBytes); // ... }; ... void* A::operator new (size_t nBytes) { return calloc (1, nBytes); } Но тогда зануление происходит только при динамическом создании объекта, а при создании как локальной переменной зануления не будет: Код (Text): A* pA = new A; // All members are cleared A a2; // Members are NOT cleared! Скорее всего придётся обнулять всё в конструкторе.
bigredcat Попробуй сделать виртуальный метод в твоём примере и вызвать его после очистки класса. Теоретически, адрес на таблицу виртуальных методов должен запортиться.
Странно, но работают и виртуальные функции. Код (Text): #include <stdio.h> #include <iostream> class A{ int val1; int val2; char* val3; public: virtual void SetVal3(char* new_val3) {val3 = new char[strlen(new_val3) + 1]; strcpy(val3, new_val3);} int GetVal1() {return val1;} virtual int GetVal2() {return val2;} virtual char* GetVal3() {return val3;} }; int main() { using std::cout; using std::endl; A a; memset((void*) &a, -1, sizeof(a)); a.SetVal3("Test"); cout << a.GetVal1() << endl; cout << a.GetVal2() << endl; cout << a.GetVal3() << endl; return 0; }
Посмотрел в debug, оказалось memset не трогает таблицу _vfptr Однако посмотрел еще раз. Оказывается еще как трогает таблицу вирт. функций (портит адреса виртуальных функций). Только не понятно, почему в примере выше виртуальные функции все-таки записывают и возвращают строку.
Для обычных методов (при вызове) компилятор сам подставляет адрес на этапе компиляции. Для виртуальных генерится код обращения к _vfptr, который занимает первые 4 байта объекта и по смещению от начала таблицы находится адрес нужной ф-ии. Фишка в том, что тип объекта у тебя может быть базовый, а _vfptr при этом может быть на таблицу виртуальных ф-ий производного класса. Так реализуется полиморфизм в cpp
Magnum Обнуление переменных: class A { ... }; A a = A(); // Вот и обнулили. А если в твоем классе "около 100 переменных", то это уже плохо - разбей класс на несколько классов по смыслу.
Magnum Любые операции над внутренними данными класса надо писать внутри класса. Все эти memset за пределами класса предложенные здесь -- просто само по себе неверное решение, так нельзя писать. Но лично меня смутило другое, что это за класс такой с сотней переменных. Это уже твоя ошибка проектирования, скорее всего. Либо класс выполняет несколько задач и его необходимо декомпозировать, как уже предложил _DEN_, либо ты забыл, что в методах могут быть локальные переменные и вынес всё в общие секции.
bigredcat Потому что в там нет виртуальности и полиморфизма. Компилятор заменил вызовы через vtable на прямые. Попробуй вот такой пример: Код (Text): class A { protected: std::string s; public: A(): s("") {}; virtual ~A() {}; virtual void set_string(std::string& new_s) { s = new_s; } virtual std::string get_str() = 0; }; class B: public A { public: B() {}; virtual ~B() {}; virtual std::string get_str() { return s; } }; int main() { A* b = new B; b->set_string(std::string("Hello")); std::cout << b->get_str() << std::endl; memset((void*)b, -1, sizeof(B)); std::cout << b->get_str() << std::endl; return 0; }
Полиморфизм, minimum edition Код (Text): class Base { public: virtual void name() { std::cout << typeid(*this).name() << std::endl; } }; class Car: public Base { /* ... */ }; class Bicycle: public Base { /* ... */ }; class Plane: public Base { /* ... */ }; void f(Base* b) { b->name(); } void main() { f(new Car); f(new Plane); f(new Bicycle); }
W4FhLF придирусь 1. http://www.research.att.com/~bs/bs_faq2.html#void-main 2. a delete для объектов кто делать будет? 3. почему нету виртуального деструктора в классе Base не ясно если я что-то выше по беседе упустил - звиняйте.