Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

arestides

Novos problemas no código

Recommended Posts

arestides

Não quero abuzar da vossa paciencia, mas estou com problemas para encontrar erros e soluções para estes em mais alguns exames. Se alguem me poder ajudar agradecia imenso.

Então ca vai:

1-

class Base{
public:
int operator == (const char *);
	//...
};
class Derived : public Base {
public:
int operator == (int);
//...
};

void main(){
Derived d1;
if (d1 == 1024 && d1 == "ana")
	//...
return d1;
}

2-

class Word {
public:
	Word(char *);
	//...
private:
	string namez;
	int occurs;
};

int main() {
//...
Word noun ("book");
Word verb = noun;
//...

return 0;
}

3-

class target_class{
friend class friend_class;

private:
	double salary;
	int rating;
};

target_class classA;

int main ()
{
char *p = (char *) &classA;

classA.rating=5;

int *pd = (int*) (p+sizeof(double));
*pd = 5;

return 0;
}

Aguardo sugestões.

O meu, muito obrigado pela ajuda que me tem dado. :thumbsup:

Share this post


Link to post
Share on other sites
mogers

1) Para além do "return d1" na função main que foi definida como void, isto tem um comportamento diferente do que eu esperava (tive de andar a experimentar o código, imagino que já o tenhas feito também). O operador == da superclasse não é herdado, mas eu não sei exactamente porquê. Parece-me que devido a existir um operador == definido em Derived, todos os operadores == da superclasse são descartados. Não tenho nenhum livro à mão, convinha verificares qual é o detalhe da herança em causa.

2) O construtor devia ter um parâmetro com o tipo "const char *" para receber uma string literal.

3) Aqui está a tentar-se quebrar o encapsulamento da classe usando conhecimentos sobre a sua implementação. "classA.rating=5;" é impedido por ser um acesso a um membro privado da classe. Mas a alteração do rating através do apontador é conseguida com sucesso (já fiz algo semelhante num projecto em C). Contudo, para além de não se dever quebrar o encapsulamento das classes, penso que a forma como os dados de um objecto são armazenados deve ser dependente da implementação do compilador e isto é outro motivo para evitar este tipo de truques.


"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Share this post


Link to post
Share on other sites
Metaluim

Como o mogers disse, isto é bastanto perigoso:

int *pd = (int*) (p+sizeof(double));

Nada te garante que a classe em memória não tem (porque muitas vezes tem) intervalos de células vazios, "padding". Daí, nunca podes assumir que os membros estão seguidos em memória pelo espaço que ocupam.

Share this post


Link to post
Share on other sites
arestides

Boas, mais uma vez muito obrigado ao mogers e ao metaluim pela ajuda.

1-Pelo que entendi o problema é a sobrecarga do operator ==, pois dois operadores com parametros diferentes tem a mesma designação. A solução pode ser declarar na classe derivada o operator == como fiend. Ex: friend int operator == (int);

2- Se declarar no construtor da classe Word: "Word (const char*);" o copy constructor default "Word verb=noun;" já copia o conteudo do objecto sem havel alterações....era esse o prblema?!

3- Nesta a violação do encapsulamento está em "*pd=5" ?como é k este ponteiro consegue aceder ao membro privado? Esta é a k esta a fazer-me mais confusão...Como deve ser reservada a memoria correctamente, com "int * pd =new int", ou o problema é o local ond ela é reservada?

Desculpem la a minha "ignorancia" na materia... :cheesygrin:

Share this post


Link to post
Share on other sites
mogers

1) Em que é que o friend ajuda?

2) Eu acho que o construtor por cópia não afecta nada visto que os atributos da classe são uma string e um inteiro. Uma string literal é uma coisa imutavel. Assim, para a usares como parametro, este tem de ser constante.

3) Isso era o que o Metalium se referia no seu post noutro tópico (teu)

http://en.wikipedia.org/wiki/Diamond_problem

o primeiro parágrafo diz tudo, mas C++, com alguns truques também podes aceder a membros privados (com apontadores) e também tens a keyword friend, que, quando uma classe Foo é "amiga" de uma classe Bar, a Foo tem acesso a toda a interface da Bar (privates incluídos).

A linguagem protege os acessos directos (como classA.rating dá erro), mas a memória não é protegida (em c++ não me parece uma coisa viável, penso que teria de ser feito em runtime e a eficiência deteriorava-se). Por isso, estes truques com apontadores podem tentar aceder aos dados privados.


"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Share this post


Link to post
Share on other sites
arestides

ok...ja entendi, obrigadão.

A função friend tem os mesmos previlegios de uma função membro da classe, mas da acesso aos campos privados de outros objectos, é utilizada mesmo para overload de operadores.

Share this post


Link to post
Share on other sites
mogers

A função friend tem os mesmos previlegios de uma função membro da classe, mas da acesso aos campos privados de outros objectos, é utilizada mesmo para overload de operadores.

Eu sei, mas não entendo qual é a sua utilidade neste caso. O problema não me parece relacionado com o encapsulamento.

Creio que o problema é que o operador == definido na superclasse não foi herdado (a minha suposição foi por haver um operador == definido na subclasse e esta ignorar os == definidos na superclasse), mas não consegui obter nenhuma referência decente na net sobre isto e não tenho nenhum livro à disposição.

Talvez alguém saiba... Metalium, fazes ideia?

PS: estou a achar estas perguntas bastante úteis para se pensar em pormenores da linguagem. Já vi que em muitas entrevistas de emprego perguntam coisas deste género. Podes disponibilizar os enunciados de exames que tens? Os que tive não costumavam ter perguntas deste género.


"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Share this post


Link to post
Share on other sites
Metaluim

O friend é um keyword que não costumo usar (acho que só usei uma vez, e não foi da maneira que é suposto ser usado).

Eu fui testar isso dos operadores, e com este código que fiz, não houve problema:

#include <iostream>

using namespace std;

class Foo
{
private:
	int m_int;

public:
	Foo (const int &intNum);
	bool operator == (const int &);

	Foo (){};
	const Foo operator = (const Foo &){};
	~Foo (){};
};

Foo::Foo (const int &intNum) : m_int(intNum)
{};

bool Foo::operator == (const int &comp)
{
return (m_int == comp) ? true : false;
}

class Bar : public Foo 
{
private:
	int m_megaInt;

public:
	Bar (const int &megaInt);
	bool operator == (const char *);
};

Bar::Bar (const int &megaInt) : m_megaInt(megaInt)
{};

bool Bar::operator == (const char *str) 
{
return (str) ? true : false;
}

int main ()  
{
Foo base(666);
Bar derived(69);

cout << ((base == 666) ? "true" : "false") << endl;

cout << ((derived == NULL) ? "true" : "false") << endl;

system("PAUSE");

return 0;
}

compilado com o g++, pois tinha-me esquecido disso, mas funcionou na mesma.

Share this post


Link to post
Share on other sites
mogers

Mas ambos == recebem um parâmetro do mesmo tipo. Naquele código da pergunta eram 2 operadores == com parametros diferentes e pelo que observei, o == definido na superclasse é descartado (e num teste rápido pareceu-me que acontece o mesmo com funções normais).

edit: ou seja, o comparador == que na superclasse comparava com um const char *, deixa de ser utilizado e a comparação obj == "coiso" dá erro (enquanto a comparação  obj == 10 funciona, tendo o operador == para ints na subclasse).


"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Share this post


Link to post
Share on other sites
TheDark

Não é descartado, tanto quanto percebi (também não tinha noção disso) é escondido.

É possível aceder-lhe de duas maneiras: ou utilizando um apontador para a classe base

Derived d1;
Base *pb = &d1;

if (d1 == 1024 && *pb == "ana") //...

ou utilizando uma referência explícita ao tipo Base

Derived d1;

if (d1 == 1024 && d1.Base::operator==("ana")) //...

Ainda não compreendi as razões para isto acontecer, mas devem existir ::thumbsup:

De qualquer forma, isto viola um pouco a abstracção... o programador tem que conhecer minimamente o tipo Base.


Desaparecido.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.