Ir ao conteúdo

C++ Programação C++ básica: classes


Ir à solução Resolvido por Ansi C,

Posts recomendados

Postado

Olá

 

Pessoal estou tendo problemas para chamar um método de uma classe em outra classe. Tipo, implementar um método da classe A para que ele utilize um método de uma classe B, isso antes de criar os objetos, somente nas definições de classes.  É possível fazer isso antes da criação do objeto? Gostaria que apontassem material ou vídeo que ensina a fazer isso.

 

valeu.

  • Curtir 1
Postado

Pra ficar mais claro vou postar o código e o erro que deu. Estou tentando resolver aquele problema do passeio do cavalo em POO criando os objetos tabuleiro e peça que irão se comunicar para que a peça (cavalo) possa visitar todas as casa sem repetir. Tenham em mente que estou só no começo e não implementei quase nada dos métodos.

 

Esse é o arquivo tabuleiro.h que contém a classe Tabuleiro.

using namespace std;

class Tabuleiro {

	//friend class Peca;

public:
	
	void desenhar(); //desenha o tabuleiro em seu estado atual
	void casasDisp(); //analisa as casas disponíveis
	void limpar(); //para limpar e atualizar a tela
	void setStatus();
	void getStatus();


private:

	int tabul[8][8] = {0};
	const int vetorMover[8][2] = {(-1, 2), ( 1, 2), ( 2, 1), ( 2,-1),
	  				              ( 1,-2), (-1,-2), (-2,-1), (-2, 1)}; //matriz com os vetores para movimento
	
};

 

Esse abaixo é a implementação dos métodos da classe e estão em um arquivo tabuleiro.cpp.

E o problema é aqui. Estou querendo utilizar o método posAtual() da classe Peca mas não estou sabendo como.

#include <iostream>
#include "tabuleiro.h"
using namespace std;


void Tabuleiro::desenhar(){

	int i, j;
	i = j = 0;
	while(i<8){
		while(j<8){
			cout << " " << Tabuleiro::tabul[i][j] << " ";
			j++;
		}
		j=0;
		i++;
		cout << endl;
	}
}

void Tabuleiro::casasDisp(){ //vai precisar saber a posição atual da peça

	int v2[1][3] = {0};
	friend class Peca::posAtual(v2); //marcador para marcar essa linha
	cout << v2[0][0] << v2[0][1] << v2[0][2];
}

void Tabuleiro::limpar(){
	system("cls");
}

void escolher(){

	
}

 

Aqui é a classe peça: peca.h

using namespace std;
class Peca{

public:
	
	friend class Tabuleiro;
	void escolher(); //método que verifica quais casas estão disponíveis e determina pra qual casa a peça irá
	void moverPeca(); //tem que ter parâmetro de entrada para saber para qual casa vai. O método escolher() fornecerá o parâmetro
	void retroceder(); //quando a peça não tiver casas disponíveis para ir deve retroceder um movimento
	void posAtual(int [1][3]); //passará/retornará a posição atual da peça

private:

	int histPos[64][3]; //histórico das posições
	int posAt[1][3]; //posição atual - terá uma coluna com o número do movimento, e mais duas com a linha e coluna q ocupa no tabuleiro
	const int vetorMover[8][2] = {(-1, 2), ( 1, 2), ( 2, 1), ( 2,-1),
						          ( 1,-2), (-1,-2), (-2,-1), (-2, 1)}; //matriz com os vetores para movimento

};

 

Aqui é a implementação de peça: peca.cpp

#include <iostream>
#include "peca.h"

using namespace std;

void Peca::posAtual(int v1[1][3]){
	int j = 0;
	while(j < 3){
		v1[1][j] = posAt[1][j];
		j++;
	}
}

 

E esse outro é o código que tem a função main, eu chamei de motor.cpp:

#include <iostream>
#include "tabuleiro.cpp"
#include "peca.cpp"

using namespace std;

int main(){

	Tabuleiro tabuleiro;

	tabuleiro.desenhar();

	system("pause");
	tabuleiro.limpar();

	tabuleiro.casasDisp();

	cout << "Sucesso!";
	return 0;
}

 

IMG DÚVIDA.jpg

Postado

esse constructo:

friend class Peca::posAtual(v2);

Não tem sentido. friend aparece na declaração das classes, nunca em outro lugar. Dentro do corpo de uma função então...

  • Solução
Postado

Olá!

Talvez me engane, mas sei que o operador :: [em palavras identificador de escopo] especifica o acesso dos módulos [ou classes se preferir] e, em específico de C++, um membro comum: é um membro declarado com a palavra-chave static.

3 horas atrás, Cris.Pavani disse:
void Tabuleiro::casasDisp(){ //vai precisar saber a posição atual da peça

	int v2[1][3] = {0};
	friend class Peca::posAtual(v2); //marcador para marcar essa linha
	cout << v2[0][0] << v2[0][1] << v2[0][2];
}

 

Logo, erraria se igual abaixo, corrigido apenas a declaração arbitrária de friend

void Tabuleiro::casasDisp(){ //vai precisar saber a posição atual da peça

	int v2[1][3] = {0};
	/*friend class*/ Peca::posAtual(v2); //marcador para marcar essa linha
	cout << v2[0][0] << v2[0][1] << v2[0][2];
}

 

Exceto se posAtual(...)  é um membro static [comum]. Se entendi correto, a classe Peça é subordinada a tabuleiro, entretanto é necessário um objeto 'Peça' para acessar os membros [privados e logicamente públicos] ou método que é comum e friend [não sei o porquê de alguém fazer isso] com parâmetro Peça.

 

Entendi que pensou conseguir acesso dos membros simplesmente com a declaração friend; sem seu objeto.

[:)Não sei dizer como funcionaria: penso que não é assim que funciona.

Postado

@RPGStreamer Após fazer a alteração sugerida, dá um erro de que não existe objeto instanciado. Eu instanciei um objeto da classe Peca criando o objeto e compilou. Mas dai fica estranho porque fica um objeto criado dentro da classe tabuleiro, dentro do método. Mas eu quero instanciar somente no arquivo principal para rodar tudo entende? Quero um jeito de fazer com que a função do Tabuleiro "saiba" que tem que usar uma função da peça para fazer o que é preciso, que no caso é verificar quais casas estão disponíveis para próximo movimento do cavalo.

Postado

Acho que já sabe que tentou criar uma referência cíclica, com Peca usando Tabuleiro e Tabuleiro usando Peca.

 

Não funciona assim. 

 

E as declarações friend estão em lugares errados.

 

Considere que não há razão para Peca depender de Tabuleiro. A posição da peça, por exemplo, não importa para a peça. Apenas para o tabuleiro e para a lógica do jogo. Apenas troque o método de lugar.

 

Em 02/01/2022 às 17:15, mauro_b disse:

Talvez me engane, mas sei que o operador :: [em palavras identificador de escopo] especifica o acesso dos módulos [ou classes se preferir] e, em específico de C++, um membro comum: é um membro declarado com a palavra-chave static

 

Nada tem a ver com static. Trata-se apenas do operador de resolução de escopo, descrito aqui na documentação em português, ou scope resolution operator

Postado
1 hora atrás, arfneto disse:

Nada tem a ver com static. Trata-se apenas do operador de resolução de escopo, descrito aqui na documentação em português, ou scope resolution operator

Entretanto, o texto destacado no link acima tem o seguinte trecho.

image.png.a90c36b3b1b195a6bd4f59735d84b04d.png

 

Não há nada para interpretar.

 

Em 02/01/2022 às 17:15, mauro_b disse:

Talvez me engane, mas sei que o operador :: [em palavras identificador de escopo] especifica o acesso dos módulos [ou classes se preferir] e, em específico de C++, um membro comum: é um membro declarado com a palavra-chave static.

 

Talvez a confusão seja porque nômeo membros estáticos com COMUM. De qualquer forma, essa discussão acabou para mim. 

 

Postado
1 hora atrás, mauro_b disse:

Não há nada para interpretar.

 

image.png.077cda39ab11e3bce5f93a034344214e.png

 

 

Sim, se deve usar :: para acessar membros estáticos, já que eles não tem uma instância para definir o escopo. Mas nada diz aí sobre o contrário: nada diz aí que o operador :: seja usado apenas para acessar membros estáticos de classes. Há muitas razões para seu uso. Muitas vezes se usa apenas para ressaltar a origem, mesmo quando o escopo já está definido.

 

 

Postado
39 minutos atrás, arfneto disse:

sado apenas para acessar membros estáticos de classes

Ninguém, além de você, disse apenas, não coloque palavras onde não há e com isso eviti estender essa discussão desnecessariamente.

 

Postado
Em 02/01/2022 às 17:15, mauro_b disse:

Talvez me engane, mas sei que o operador :: [em palavras identificador de escopo] especifica o acesso dos módulos [ou classes se preferir] e, em específico de C++, um membro comum: é um membro declarado com a palavra-chave static

 

Foi você, @mauro_b que escreveu isso. E pela ressalva já no início se vê que não estava seguro.  E não está correto. Apenas expliquei porque. Não é ideia minha. Trata-se da linguagem C++. Em especial o final do parágrafo 

 

Em 02/01/2022 às 17:15, mauro_b disse:

em específico de C++, um membro comum: é um membro declarado com a palavra-chave static.

 

não faz sentido e mereceria redação mais elaborada.

 

Só comentei no sentido de esclarecer aos leitores do tópico.

 

3 horas atrás, mauro_b disse:

De qualquer forma, essa discussão acabou para mim. 

 

Note que há um botão para tal  image.png.cf60a643c763c7c63e7b20f3986f0cc1.pnge pode apenas desmarcar em sua sessão.

 

36 minutos atrás, mauro_b disse:

Ninguém, além de você, disse apenas, não coloque palavras onde não há e com isso eviti estender essa discussão desnecessariamente

 

Leia e cite algo que mantenha o contexto da frase, por favor. 

 

Em C++: o operador de resolução de escopo é necessário (claro) para acessar métodos estáticos de uma classe, porque pode não haver uma instância para acessá-los. No entanto o operador não existe para isso. Esse era o sentido do apenas e está claro lá e obscuro no texto que escreveu e por isso deixei essas notas.

 

Poste um código sobre o que está tentando explicar...

 

Postado

@arfneto

3 horas atrás, arfneto disse:

Acho que já sabe que tentou criar uma referência cíclica, com Peca usando Tabuleiro e Tabuleiro usando Peca.

 

Não funciona assim. 

 

E as declarações friend estão em lugares errados.

 

Considere que não há razão para Peca depender de Tabuleiro. A posição da peça, por exemplo, não importa para a peça. Apenas para o tabuleiro e para a lógica do jogo. Apenas troque o método de lugar.

 

 

Opa.

 

Gostaria que você só analisasse se o meu entendimento está correto: pelo que entendi não é possível criar um método que chame um método de um OUTRA classe antes da instanciação, ou seja, antes de criar um objeto. É isso?.

Caso eu queira utilizar um método que precise de um dado fornecido por função de outra classe então eu terei de programar na função main() após a instanciação das classes (criação dos objetos), correto?

 

Cara, obrigado pela atenção.

  • Curtir 1
Postado

Primeiro diz

4 horas atrás, arfneto disse:

Nada tem a ver com static.

 

Depois diz 

1 hora atrás, arfneto disse:

im, se deve usar :: para acessar membros estáticos, já que eles não tem uma instância para definir o escopo. Mas nada diz aí sobre o contrário: nada diz aí que o operador :: seja usado apenas para acessar membros estáticos de classes. Há muitas razões para seu uso. Muitas vezes se usa apenas para ressaltar a origem, mesmo quando o escopo já está definido.

 

Sugere que tem algo haver, porém não apenas, como se isso corrige algo.

 

 

22 minutos atrás, arfneto disse:

Leia e cite algo que mantenha o contexto da frase, por favor. 

 

Em C++: o operador de resolução de escopo é necessário (claro) para acessar métodos estáticos de uma classe, porque pode não haver uma instância para acessá-los. No entanto o operador não existe para isso. Esse era o sentido do apenas e está claro lá e obscuro no texto que escreveu e por isso deixei essas notas.

 

Poste um código sobre o que está tentando explicar...

Depois se corrige pela segundo vez. E de maneira alguma isso me ajudou.

Postado
1 minuto atrás, Cris.Pavani disse:

Gostaria que você só analisasse se o meu entendimento está correto: pelo que entendi não é possível criar um método que chame um método de um OUTRA classe. É isso?.

 

Sim, seu entendimento está correto.

 

O que não pode ter é uma referência cíclica.

 

1 minuto atrás, Cris.Pavani disse:

Caso eu queira utilizar um método que precise de um dado fornecido por função de outra classe então eu terei de programar na função main() após a instanciação das classes (criação dos objetos), correto?

 

Só a lógica do programa vai dizer. Pode ter classes internas também, em casos em que uma classe só tem sentido dentro de outra. Basta que a classe seja conhecida no momento em que é usada na outra. 

2 minutos atrás, mauro_b disse:

Depois se corrige pela segundo vez. E de maneira alguma isso me ajudou.

 

@mauro_b  sinto que não tenha ficado claro. Vou escrever um exemplo depois. 

3 minutos atrás, mauro_b disse:

Sugere que tem algo haver, porém não apenas, como se isso corrige algo.

 

Aparentemente você está confundindo causa com consequência.

  • Quando precisa acessar um método estático
  • E se não tem uma instância da classe

ENTÃO precisa do operador :: para indicar ao compilador onde está o método em questão.

 

Mas em muitos outros casos precisa ou pode usar esse operador nessa linguagem. O contrário não é verdadeiro.

 

De todo modo depois posto um exemplo.

 

 

Postado

Imagino que entenda esse exemplo, @mauro_b onde pode ver o que eu tentei explicar: funções e variáveis estáticas e o uso de
 

::


para identificar escopo. Inclusive para permitir acesso ao escopo global. ;) 

 

#include <iostream>

class ex1
{
   public:
    static int const valor = 42;
    int              outro;
    ex1() : outro(1){};
    ex1(int v) : outro(2){};

    static auto f1()
    {
        std::cerr << "valor: " << ex1::valor << "\n";
        return ex1::valor;
    };

    auto f2()
    {
        std::cerr << "valor: " << valor << " outro: " << outro << "\n";
        return valor + outro;
    };
};

auto f1()
{
    std::cerr << "(main) valor: " << ex1::valor << "\n";
    return ex1::valor + 22;
};

int main(void)
{
    std::cout << "Acessando via ::f1() " << ex1::f1() << "\n";
    ex1 um(42);
    std::cout << "Acessando via um.f1() " << um.f1() << "\n";
    ex1 outro;
    std::cout << "Acessando via outro.f1() " << outro.f1() << "\n";
    std::cout << "Acessando f1() global " << ::f1() << "\n";
    std::cout << "Valor da variavel estatica na classe = " <<
        ex1::valor << "\n";
}

 

Eis a saída

 

valor: 42
Acessando via ::f1() 42
valor: 42
Acessando via um.f1() 42
valor: 42
Acessando via outro.f1() 42
(main) valor: 42
Acessando f1() global 64
Valor da variavel estatica na classe = 42

 

Postado

@arfneto Imaginei que demostraria o static e o operador :: sem relação!

Porque quando alguém diz que algo não tem relação (ou "Nada tem a ver") é porque não tem mesmo!

 

E por qual motivo eu trouxe static para uma discussão de friend?

Em 02/01/2022 às 13:37, Cris.Pavani disse:
void Tabuleiro::casasDisp(){ //vai precisar saber a posição atual da peça

	int v2[1][3] = {0};
	friend class Peca::posAtual(v2); //marcador para marcar essa linha
	cout << v2[0][0] << v2[0][1] << v2[0][2];
}

Por conta desta imagem a imagem abaixo e do trecho acima que me fez pensar; A autora corrigiu "friend class" na declaração, mas não pode acessar o método porque ele não é comum [ou estático]

 

image.png.6c24f9db379fd308849661a644cdf7cd.png

 

 

Sem essa imagem a discussão não existiria;

  • Confuso 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...