minhas informações de contato
Correspondência[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Índice
4. Funções de membro padrão de classes
Formato de definição de classe
class é a palavra-chave que define a classe, Stack é o nome da classe e {} é o corpo da classe. Observe que o ponto e vírgula no final da definição não é omitido. O conteúdo do corpo da classe é chamado de membro da classe: as variáveis da classe são chamadas de atributos ou as funções de membro da classe são chamadas de métodos ou funções de membro da classe;
- //text.cpp
- #include<iostream>
- using namespace std;
-
- class Stack
- {
-
- //成员变量
- int* a;
- int top;
- int capacity;
- //成员函数
- void Push()
- {
-
- }
- void Pop()
- {
-
- }
- };//分号不能省略
- int main()
- {
-
-
- return 0;
- }
- //为区分成员变量,一般前面加_
- //成员变量
- int* _a;
- int _top;
- int _capacity;
C++ é uma forma de implementar encapsulamento, usando classes para combinar as propriedades e métodos de um objeto para torná-lo mais completo e fornecer seletivamente sua interface para usuários externos por meio de direitos de acesso.
- //text.cpp
- #include<iostream>
- using namespace std;
-
- class Stack
- {
-
-
- ///
-
- void Push()
- {
-
- }
- //Push 没给限定符 class默认私有 private
- ///
- public:
- void Pop()
- {
-
- }
- int Swap()
- {
-
- }
- //Pop和Swap 被public修饰,直到下一个限定符出现之前都为公有
- ///
- protected:
- int add();
- //add 被public修饰,直到下一个限定符出现之前都为保护
- /// /
-
- private:
-
- int* _a;
- int _top;
- int _capacity;
- //成员变量被private修饰,直到}结束都为私有
- };
- int main()
- {
- Stack st;
- //公有可以访问
- st.Pop();
- st.Swap();
- //私有不可访问
- st._top;
-
-
-
- return 0;
- }
Notas Adicionais:
A classe define um novo escopo. Todos os membros da classe estão no escopo da classe. Ao definir membros fora da classe, você precisa usar o operador ::scope para indicar a qual escopo de classe o membro pertence.
O domínio de classe afeta as regras de pesquisa de compilação. Se Init no programa a seguir não especificar o domínio de classe Stack, o compilador tratará Init como uma função global. Se não conseguir encontrar membros como _top durante a compilação, ele irá para o. domínio de classe para encontrá-los.
- //text.cpp
- #include<iostream>
- using namespace std;
-
- class Stack
- {
-
-
- public:
- void Init(int x, int y);
-
- };
- void Stack::Init(int x, int y)
-
- {
- _top = x;
- _capacity = y;
- }
- int main()
- {
-
- return 0;
- }
Perceber:
- //text.cpp
- #include<iostream>
- using namespace std;
-
- class Stack
- {
-
- //声明
-
- int* _a;
- int _top;
- int _capacity;
-
- };
-
- int main()
- {
-
- Stack::_top = 2024;
- //编译器报错,_top只是声明,并未实例化
-
- return 0;
- }
-
- //text.cpp
- #include<iostream>
- using namespace std;
-
- class Stack
- {
-
-
- //声明
- int* _a;
- int _top;
- int _capacity;
-
- };
-
- int main()
- {
-
-
- Stack st;
- st._top=2024;
- //Stack实例化出st,系统已经给st分配内存了,可以存储数据,编译通过
-
- return 0;
- }
-
-
Regras de alinhamento de memória
- class A
- {
- public:
- void Print()
- {
- cout << _ch << endl;
- }
- private:
- char _ch;
-
- int _i;
- };
- //_ch 是一个字节,默认对齐数是4,最大对齐数是4,所以开辟4个字节用来存在_ch
- // _i是4个字节,默认对齐数是4,最大对齐数是4,所以开辟4个字节用来存储_i
- class B
- {
- public:
- void Print()
- {
- //。。。
- }
-
-
- };
- class B
- {
-
-
- };
- //B和C里面没有存储任何成员变量,只有一个函数,可成员函数不存对象里面
- // 按理来说是0,但是结构体怎么会没大小,为表示对象存在C++对这种规定大小为1,为了占位标识对象存在
Após a compilação do compilador, as funções-membro da classe adicionarão um ponteiro para a classe atual na primeira posição do parâmetro formal por padrão, chamado de ponteiro.
Por exemplo, o protótipo Init na classe Date é void Init (Data * const this, int ano, int mês, int dia Ao acessar variáveis-membro nas funções-membro da classe, a essência é acessada por meio do ponteiro this). como _year na função Init, this->_year=year.
protótipo:
- class Date
- {
- void Print()
- {
-
- cout << _year << "n" << _month << "n" << _day << endl;
- }
- void Init( int year, int month,int day)
- {
- _year = year;
- _month = month;
- _day = day;
-
- }
-
- private:
- int _year;
- int _month;
- int _day;
-
- };
-
- Date d1;
- d1.Init(2024,7,10);
-
- d1.Print();
- Date d2;
-
- d2.Init(2024, 7, 9);
- d2.Print();
-
protótipo real
- class Date
- {
- void Init(Date* const this,int year, int month,int day)
-
- {
- this->_year = year;
- this->_month = month;
- this->_day = day;
-
- }
- void Printf(Date* const this)
-
- {
-
- cout << this->_year << "n" <<this-> _month << "n" << this->_day << endl;
- }
- private:
- int _year;
- int _month;
- int _day;
-
- };
- Date d1;
- d1.Init(&d1,2024,7,10);
- d1.Print(&d1);
-
- Date d2;
- d2.Init(&d2,2024, 7, 9);
- d2.Print();
C++ estipula que não é permitido escrever este ponteiro na posição de parâmetros reais e parâmetros formais (o compilador irá lidar com isso durante a compilação), mas este ponteiro pode ser usado explicitamente no corpo da função. o conteúdo apontado por este ponteiro pode
este ponteiro é armazenado na pilha
A função de membro padrão é uma função de membro que não é definida explicitamente pelo usuário e é gerada automaticamente pelo compilador. É chamada de função de membro padrão.
O construtor é uma função de membro especial. Deve-se notar que embora o construtor seja chamado de construtor, o conteúdo principal do construtor não é abrir espaço para criar objetos (o objeto local que normalmente usamos é o espaço que é aberto quando. o quadro de pilha é criado) ), mas o objeto é inicializado quando o objeto é instanciado. A essência do construtor é substituir a função Init que escrevemos anteriormente nas classes Stack e Date. A chamada automática do construtor substitui perfeitamente a função Init.
Recursos do construtor:
- class Date
- {public:
- //1.无参构造函数
- Date()
- {
- _year = 1;
- _month = 1;
- _day = 1;
- }
- //2.带参构造函数
- Date(int year, int month, int day)
- {
- _year = year;
- _month = month;
- _day = day;
- }
-
-
- //3.全缺省构造函数
- Date(int year = 1, int month = 1, int day = 1)
- {
- _year = year;
- _month = month;
- _day = day;
- }
- private:
- int _year;
- int _month;
- int _day;
-
- };
O construtor sem parâmetros, o construtor totalmente padrão e o construtor gerado pelo compilador por padrão quando não escrevemos um construtor são todos chamados de construtores padrão. Mas apenas um destes três pode existir, não ao mesmo tempo. Embora o construtor sem parâmetros e o construtor padrão completo constituam uma sobrecarga de função, haverá ambiguidade ao chamá-los.Observe que não apenas o construtor padrão é aquele gerado pelo compilador por padrão, ele é o construtor, o construtor sem parâmetros, e o construtor padrão completo também é o construtor padrão. Resumindo, ele pode ser chamado sem passar parâmetros.
Não escrevemos. A construção gerada pelo compilador por padrão não possui requisitos para a inicialização de variáveis de membro do tipo interno. Ou seja, se é inicializado ou não, é incerto, depende do compilador.
- //text.cpp
- #include<iostream>
- using namespace std;
- typedef int STDataType;
- class Stack
- {
- public:
- Stack(int n = 4)
- {
- _a = (STDataType*)malloc(sizeof(STDataType) * n);
- if (nullptr == _a)
- {
- perror("malloc申请失败");
- }
- _capacity = n;
- _top = 0;
- }
-
- private:
- STDataType* _a;
- size_t _capacity;
- size_t _top;
- };
- //两个Stack实现队列
- class MyQueue
- {
- private:
- int size;
- Stack pushst;
- Stack popst;
- };
-
- int main()
- {
-
- MyQueue my;
-
-
- return 0;
- }
-
C++ divide os tipos em tipos personalizados e tipos integrados (tipos básicos). Tipos integrados são os tipos de dados nativos fornecidos pela linguagem, como int/char/double/pointer, etc. Tipos personalizados são tipos que nós mesmos definimos usando palavras-chave como class/struct.O construtor aqui é inicializado automaticamente e o VS também inicializa o tamanho do tipo integrado. Diferentes compiladores têm diferentes valores de inicialização e C++ não os especifica.
Para variáveis de membro de tipo personalizado, é necessário chamar o construtor padrão desta variável de membro para inicializá-la.Se esta variável membro não tiver um construtor padrão, um erro será relatado. Se quisermos inicializar esta variável membro, precisamos usar uma lista de inicialização para resolvê-la.
Resumo: Na maioria dos casos, precisamos implementar o construtor nós mesmos. Em alguns casos, é semelhante ao MyQueue e quando Stack tem um construtor padrão, MyQueue pode ser gerado e usado automaticamente.
- ~Stack()
- {
- free(_a);
- _a = nullptr;
- _top = _capacity = 0;
- }
Características do destruidor:
1. O nome do destruidor é precedido por caracteres ~
2. Sem parâmetros e sem valor de retorno (consistente com o construtor)
3. Uma classe só pode ter um destruidor.Se a definição não for exibida, o sistema gerará automaticamente um destruidor padrão.
4. Quando o ciclo de declaração do objeto terminar, o sistema chamará automaticamente o destruidor.
5. Semelhante ao construtor, não escrevemos o destruidor gerado automaticamente pelo compilador e não processamos os membros do tipo integrado que chamarão outros destruidores.
6. Também deve ser observado que quando exibirmos o destruidor, o destruidor do membro do tipo customizado também será chamado, o que significa que o destruidor do membro do tipo customizado será chamado automaticamente independentemente da situação.
- //text.cpp
- #include<iostream>
- using namespace std;
- typedef int STDataType;
- class Stack
- {
- public:
- Stack(int n = 4)
- {
- _a = (STDataType*)malloc(sizeof(STDataType) * n);
- if (nullptr == _a)
- {
- perror("malloc申请失败");
- }
- _capacity = n;
- _top = 0;
-
-
- }
-
- ~Stack()
- {
- free(_a);
- _a = nullptr;
- _top=_capacity=0;
- }
- private:
- STDataType* _a;
- size_t _capacity;
- size_t _top;
-
- };
- //两个Stack实现队列
- class MyQueue
- {public:
- //编译器默认生成MyQueue的构造函数调用了Stack的构造,完成了两个成员的初始化
- //编译器默认生成MyQueue的析构函数调用了Stack的析构,释放了Stack内部的资源
- //显示写析构也会调用Stack的析构
- ~MyQueue()
- {
- cout << "~MyQueue" << endl;
- }
- private:
-
- Stack pushst;
- Stack popst;
-
- };
-
-
- int main()
- {
-
- MyQueue my;
-
-
- return 0;
- }
O destruidor em MyQueue não faz nada, mas o C++ estipula que outros destruidores serão chamados para liberar a memória.
Se nenhum recurso for solicitado, o destruidor não precisa ser escrito e o destruidor padrão gerado pelo compilador pode ser usado diretamente, como Date. Se o destruidor padrão gerado puder ser usado, não há necessidade de escrever explicitamente o destruidor. como MyQueue, mas há um aplicativo de recursos. Ao destruir, certifique-se de escrever o destruidor diretamente, caso contrário, causará vazamento de recursos, como Stack.
-
-
- bool operator<(Date d1, Date d2)
- {
-
- }
- bool operator==(Date d1,Date d2)
- {
- return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
- }
- //text.cpp
- #include<iostream>
- using namespace std;
-
- class Date
- {
- public:
- Date(int year, int month, int day)
- {
- _year= year;
- _month = month;
- _day = day;
-
- }
-
-
-
- int _year;
- int _month;
- int _day;
-
- };
-
- bool operator<(Date d1, Date d2)
- {
-
- }
- bool operator==(Date d1,Date d2)
- {
- return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
- }
- int main()
- {
-
- Date d1(2024, 7, 10);
- Date d2(2024,7,9);
- //两种用法都可以
- d1 == d2;
- operator==(d1 , d2);
- return 0;
- }