Você está na página 1de 4

Universidade Federal de Mato Grosso do Sul

Faculdade de Computao

Linguagem de Programao Orientada a Objetos


Paulo A. Pagliosa
PROVA 1
19/01/2013
GABARITO
Questo 1 (6.0)
Considere as seguintes declaraes C++:
struct Point2D
{
Point2D() {}
Point2D(int x, int y)
{
this->x = x;
this->y = y;
}
int x;
int y;
};

class Shape2D
{
public:
Shape2D(Figure2D& f): figure(&f)
{
f.addShape(this);
}
virtual ~Shape2D() {}
virtual void draw() const = 0;
protected:
Figure2D* figure;

class Shape2D;
private:
Shape2D* next;
friend class Figure2D;
};

class Figure2D
{
public:
Figure2D():
shapes(0),
numberOfShapes(0)
{
}
~Figure2D()
{
clear();
}
void draw() const;
void addShape(Shape2D*);
void clear();
private:
Figure2D(const Figure2D&);
Figure2D& operator =(const Figure2D&);
Shape2D* shapes;
int numberOfShapes;
};

class Polygon2D: public Shape2D


{
public:
Polygon2D(Figure2D& f, int n):
Shape2D(f)
{
points = new Point2D[n];
numberOfPoints = n;
}
Polygon2D(const Polygon2D&);
~Polygon2D()
{
delete []points;
}
int getNumberOfPoints() const;
const Point2D& operator[](int) const;
Point2D& operator[](int);
void draw() const;
private:
Point2D* points;
int numberOfPoints;
};

(a) (2.0) A funo C++ abaixo deveria criar um quadrado de lado 2a e centro c:
Polygon2D createSquare(Figure2D& f, const Point2D& c, int a)
{
Polygon2D p(f, 4);
p[0] =
p[1] =
p[2] =
p[3] =
return
}

Point2D(c.x
Point2D(c.x
Point2D(c.x
Point2D(c.x
p;

+
+

a,
a,
a,
a,

c.y
c.y
c.y
c.y

+
+

a);
a);
a);
a);

Por que createSquare() no funciona como esperado? Qual(is) correo(es) voc efetuaria na funo
ou na classe Polygon2D para resolver o(s) problema(s)?
SOLUO
H dois erros na funo. O primeiro, de ordem semntica, ocorre na declarao
Polygon2D p(f, 4);

Aqui, tenta-se criar estaticamente um objeto p da classe Polygon2D. Ocorre que Polygon2D uma
classe abstrata e, como tal, no admite instncias (erro de compilao). Polygon2D abstrata porque
deriva da classe abstrata Shape2D e no sobrepe o mtodo abstrato Shape2D::draw(). A soluo para
este problema tornar a classe Polygon2D concreta, ou seja, declarar o mtodo:
class Polygon2D: public Shape2D
{
public:
void draw() const;
...
};

O segundo erro, admitida a possibilidade de criao esttica do objeto p, que este criado localmente
e reside, neste caso, na poro de memria do segmento de pilha destinada a cada execuo da funo
createSquare(). Quando o fluxo de execuo transferido para fora do bloco da funo, em
return p;

o objeto p automaticamente destrudo e, com isso, o destrutor declarado em Polygon2D invocado


pelo compilador. Este libera a memria dinmica reservada para armazenamento do vetor de pontos
points de p. Mas como o objeto p deve ser retornado pela funo, o compilador cria um objeto temporrio com uma cpia de p, o qual inicializado atravs do construtor de cpia. Como no h construtor
de cpia explicitamente declarado em Polygon2D, o compilador prov um que implementa a semntica
de cpia rasa. Como consequncia, o atributo points do temporrio ter o mesmo valor do atributo
points de p, mas como p ser destrudo, points do temporrio ser um ponteiro pendente. Solues
para o problema:
Declarar um construtor de cpia em Polygon2D que implemente a semntica de cpia profunda
(ineficiente em termos de consumo de memria e processamento, mas funciona):
Polygon2D::Polygon2D(const Polygon2D& p): Shape2D(*p.figure)
{
points = new Point2D[numberOfPoints = p.numberOfPoints];
// duplica os pontos de p em *this
for (int i = 0; i < numberOfPoints; i++)
points[i] = p.points[i];
}

Fazer a funo retornar um ponteiro para Polygon2D e criar o objeto dinamicamente:


Polygon2D* createSquare(Figure2D& f, const Point2D& c, int a)
{
Polygon2D* p = new Polygon2D(f, 4);
(*p)[0] =
(*p)[1] =
(*p)[2] =
(*p)[3] =
return p;

Point2D(c.x
Point2D(c.x
Point2D(c.x
Point2D(c.x

+
+

a,
a,
a,
a,

c.y
c.y
c.y
c.y

+
+

a);
a);
a);
a);

Passar para a funo uma referncia (ou ponteiro) de um Polygon2D criado fora da funo (mas
neste caso a semntica de createSquare() perde o sentido, pois a funo no est de fato
criando um polgono, apenas definindo os pontos de um j criado):
void createSquare(Polygon2D& p, const Point2D& c, int a)
{
p[0] = Point2D(c.x a, c.y a);
p[1] = Point2D(c.x + a, c.y a);
p[2] = Point2D(c.x + a, c.y + a);
p[3] = Point2D(c.x a, c.y + a);
return p;
}

(b) (1.0) Seja p um objeto da classe Polygon2D. Quais mtodos da classe so acoplados s mensagens
da sentena a seguir? Justifique.
p[0] = p[1];

SOLUO
Na expresso acima h dois acoplamentos mensagem/mtodo da classe Polygon2D.
Mensagem p[0], ou p.operator [](0): acoplado o mtodo Polygon2D::operator [](int),
pois o objeto p receptor da mensagem no const, uma vez que aparece do lado esquerdo de
uma expresso de atribuio.
Mensagem p[1], ou p.operator [](1): acoplado Polygon2D::operator [](int) const, pois
o objeto p receptor da mensagem const, uma vez que aparece do lado direito de uma expresso
de atribuio.
(c) (1.0) Qual o significado da declarao
friend class Figure2D;

na classe Shape2D? Critique sua utilizao.


SOLUO
Significa que a classe Figure2D amiga da classe Shape2D, isto , mtodos da primeira podem acessar
quaisquer membros (inclusive os protegidos e privados) da segunda. Enquanto a declarao de classes
amigas fere a propriedade do encapsulamento, seu uso se justifica neste caso porque h uma relao
forte de dependncia entre as classes, visto que um objeto do tipo Figure2D um continer de objetos
de tipo Shape2D. Assim, no necessria a declarao de um getter e um setter em Shape2D a fim de
que Figure2D possa manipular o atributo privado Shape2D::next (alis, a declarao de tal getter e
setter em Shape2D permitiria que qualquer outro objeto ou funo pudesse manipular o atributo, o que
no deve ser permitido, visto que essa uma exclusividade de Figure2D).
(d) (1.0) Seja a classe Line2D, diretamente derivada de Shape2D. Liste qual(is) o(s) erro(s) em:
Line2D* p = new Shape2D(*new Figure2D());
Figure2D f1, f2 = f1;

SOLUO
Na primeira declarao, a classe Shape2D abstrata e no admite instncia. Alm disso, no possvel
atribuir a um ponteiro da classe derivada Line2D o endereo de um objeto da classe base Shape2D. Na
segunda, o construtor de cpia em Figure2D privado e no pode ser acessado na declarao
Figure2D f2 = f1;

(e) (1.0) Seja o mtodo


void Figure2D::draw() const
{
for (Shape2D* p = Shapes; p != 0; p = p->next)
p->draw();
}
Discuta o tipo de acoplamento que ocorre na mensagem p->draw() e qual(is) o(s) benefcio(s) disso.

SOLUO
A varivel p um ponteiro para um objeto da classe Shape2D. Uma vez que Shape2D::draw() virtual,
o acoplamento ser dinmico (juno posterior), ou seja, o mtodo acoplado mensagem ser o mtodo
draw() da classe do objeto cujo endereo, em tempo de execuo, estiver atribudo ao ponteiro p. Em
resumo, o maior benefcio cdigo velho funcionando com cdigo novo, sem necessidade de sentenas
do tipo switch-case.
Questo 2 (2.0)
Seja p uma referncia para um objeto de uma classe C, a qual est inserida em algum ponto em uma
hierarquia de classes, ou seja, a classe C possui classes bases e classes derivadas. Suponha que
void m();

seja um mtodo da classe C. Na mensagem


p.m();

explique como ocorre o acoplamento mensagem/mtodo, considerando que em alguma classe base de C
o mtodo m()tenha sido declarado como (a) virtual e (b) no virtual.
SOLUO
Se o mtodo C::m() no for virtual, ento C::m() ser acoplado (independentemente do tipo do objeto
referenciado por p), uma vez que p uma referncia para a classe C, ou seja, o acoplamento esttico
(determinado em tempo de compilao). Se o mtodo C::m() for virtual, ento o mtodo a ser acoplado
mensagem ser aquele da classe do objeto referenciado por p em tempo de execuo. Esse tipo de
acoplamento chamado ACOPLAMENTO DINMICO ou JUNO POSTERIOR, pois resolvido durante a
execuo do programa.
Questo 3 (2.0)
Considere o cdigo C++ a seguir.
1
2
3
4
5
6
7
8
9
10
11

template <typename T>


T f(const T& a, const T& b)
{
T temp;
if (a <= b)
temp = b a;
else
temp = b + a;
return temp;
}

Quais as operaes sobre o tipo T a fim de que o template possa ser instanciado sem erros?
SOLUO
Considerando que T no um tipo primitivo, as operaes so: construtor default pblico, usado na linha
4, e operadores pblicos <=, - binrio e + binrio, usados nas linhas 6, 7 e 9, respectivamente. Se o
programador da classe T declarar operador de cpia, usado nas linhas 7 e 9, e destrutor e construtor de
cpia, usados na linha 10, estes devem ser pblicos.

Boa Prova!

Você também pode gostar