Intrebare de interviu

Intrebari despre limbajul C++, standardul C++, STL, OOP in C++ sau alte subiecte nelegate de VisualC++
Felics
Junior
Junior
Posts: 2
Joined: 11 May 2011, 12:00
Judet: Dolj

Intrebare de interviu

Post by Felics » 11 May 2011, 12:27

Am codul:

Code: Select all

class A
{
	private:
		A(){};
		~A(){};

	public:
		int sum(int a, int b){return a + b;}
};
Intrebarea este cum apelez functia sum fara sa modific clasa A.



User avatar
zlatomir
Membru++
Membru++
Posts: 282
Joined: 04 Jul 2009, 23:59
Location: Arad
Contact:

Re: Intrebare de interviu

Post by zlatomir » 11 May 2011, 13:08

Raspuns:

Code: Select all

#include <iostream>

#define private public

class A
{
   private:
      A(){};
      ~A(){};

   public:
      int sum(int a, int b){return a + b;}
};

int main() {
	A obj;
	std::cout << obj.sum(1, 1) << "\n";
}
//dar cel mai probabil raspunsul acceptat este: nu trebuie sa facem asta si eventual ceva bla-bla ca ala care a conceput clasa a facut-o asa pt un motiv anume si asta ar putea fi un hack care sa duca in viitor la probleme.

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Intrebare de interviu

Post by Silviu Ardelean » 11 May 2011, 13:23

O varianta mai curata dar nu imaculata:

Code: Select all

class B : public A
{
public:
	B() {}
	~B() {}

	int sumX(int a1, int b1) { 
		return sum(a1,b1);
		}
};

int main()
{
	B z;
	z.sumX(2,3);
}

User avatar
zlatomir
Membru++
Membru++
Posts: 282
Joined: 04 Jul 2009, 23:59
Location: Arad
Contact:

Re: Intrebare de interviu

Post by zlatomir » 11 May 2011, 13:36

Silviu varianta ta nu merge, constructorul/destructorul lui A e inaccesibil, trebuie sa te murdaresti daca vrei sa faci murdarii.

O mica "imbunatatire" ar fi sa includem header-ul A.h intre doua #define-uri (pt a repune private-ul in joc pt alte clase)

Code: Select all

#define private public
#include "a.h"
#define private private
//dar tot cod naspa se numeste

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Intrebare de interviu

Post by Silviu Ardelean » 11 May 2011, 13:41

M-ai pacalit... :) uitasem define-ul tau si fireste ca mi se compila (desigur constructorul A nu putea fi accesat la creearea obiectului).

LE. Ideea initiala era sa folosesc o clasa friend dar "enuntul" nu permitea:

Code: Select all

class A
{
   private:
      A(){ };
      ~A(){ };

   public:
  
  friend class B;
  int sum(int a, int b)  {return a + b;}
};

class B 
{
public:
	B() {};
	~B() {};

	int sumX(int a1, int b1) { 		
		A  x;
		return x.sum(a1,b1);
		}
};

int main()
{
	B z;
	int x = z.sumX(2,3);
}
Last edited by Silviu Ardelean on 11 May 2011, 16:22, edited 1 time in total.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Intrebare de interviu

Post by Ovidiu Cucu » 11 May 2011, 13:58

Simplu si elegant, uite-asa:

Code: Select all

   A* pA = NULL;
   int s = pA->sum(666, 777);

0ptr
Membru
Membru
Posts: 71
Joined: 01 Feb 2011, 23:27
Judet: Ilfov

Re: Intrebare de interviu

Post by 0ptr » 11 May 2011, 20:17

Silviu Ardelean wrote:M-ai pacalit... :) uitasem define-ul tau si fireste ca mi se compila (desigur constructorul A nu putea fi accesat la creearea obiectului).

LE. Ideea initiala era sa folosesc o clasa friend dar "enuntul" nu permitea:

Code: Select all

class A
{
   private:
      A(){ };
      ~A(){ };

   public:
  
  friend class B;
  int sum(int a, int b)  {return a + b;}
};
Silviu, ai incalcat regula si ai modificat clasa. :)

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Intrebare de interviu

Post by Silviu Ardelean » 11 May 2011, 21:43

0ptr wrote:Silviu, ai incalcat regula si ai modificat clasa. :)
Desigur. Am facut-o pentru ca problema e atat de "practica". E la minta cocosului ca in acest caz initial ciclul "V" de creeare si distrugere a obiectului nu s-ar creea.
Cum si daca as face functia statica as incalca regula.
Consider ca mult mai practica si interesanta ar fi abordarea in care constructorul e protected. Atunci ai vedea daca pe interievat il duce capul sa deriveze si sa foloseasca adecvat functia sum().

User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

Re: Intrebare de interviu

Post by Marius Bancila » 11 May 2011, 22:49

Smecheria e cea care a aratat-o Ovidiu, sa folosesti un pointer NULL; nu apelezi constructorul (neconstruind nimic), dar poti apela functia pentru ca nu acceseaza date/stare din clasa respectiva. De fapt, corect daca tot e sa vorbim, functia respectiva ar fi trebuit sa fie const. Ei asa e cu intrebarile de interviu, mai dai si rateuri.
Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Intrebare de interviu

Post by Ovidiu Cucu » 12 May 2011, 10:00

Totul porneste de la feelingul multora ca "functiile membru statice apartin clasei, pe cand cele non-statice apartin obiectelor".
Deci "musai si obligatoriu, pentru a apela orice metoda non-statica trebuie instantiat un obiect".
(cred ca am scos si eu un astfel de porumbel la un interviu, acum vreo 15 ani) . :D
E ca si cum, daca as avea o clasa cu o metoda non-statica pentru care as instantia N obiecte, bietul compilator ar trebui sa genereze N functii.

De fapt, compilatorul genereaza o singura functie caruia ii transmite "din oficiu" adresa obiectului prin intermediul careia acceseaza ceilalti membri din acel obect.
Acea adresa este ceva de care a auzit mai toata lumea: minunatul pointer 'this'.

Fortand putin denumirile si ignorand faptul ca am o metoda inline, functia rezultata din A::sum s-ar putea scrie intr-o maniera "pur procedurala" cam asa:

Code: Select all

int A_sum(A* const This, int a, int b)
{
   return a + b;
}
Daca 'This' e adresa unui obiect valid sau e NULL, muci sau carcalaci, cui ii pasa?
Nu e folosit deci, NO PROBLEM.

Daca in schimb, am completa putin clasa A dupa cum urmeaza:

Code: Select all

class A
{
   int m;
   A() {}
public:
   void sum(int a, int b) {m = a + b;}
};
Atunci ar rezulta ceva de genul

Code: Select all

void A_sum(A* const This, int a, int b)
{
   This->m = a + b;
}
Sau ceva mai explicativ in contextul nostru:

Code: Select all

void A_sum(A* const This, int a, int b)
{
   *((int*)((char*)This + offsetof(A, m))) = a + b;
   // pe romaneste: se atribuie valoarea intreaga (a + b)
   // la adresa din memorie egala cu adresa obiectului (This) 
   // plus offsetul in bytes al membrului m in cadrul clasei A (offsetof(A, m)).
   // Clar sau trebuie un film color in 3D? :)))  
}
Daca 'This' pointeaza la un obiect valid atunci e OK.
Daca in schmb e NULL sau arata spre balarii, atuci nashpa: culege nene programul din balarii! :)

// Unde nu se intelege sau gresesc, va rog sa ma trageti de maneca. Nobody is perfect. ;)

[ va urma ]

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Intrebare de interviu

Post by Ovidiu Cucu » 12 May 2011, 12:32

[ continuare ]

Acuma tot o intrebare de interviu (posibil, continuare la prima):

Q: E OK, are sens sa declaram non-statica o functie membru a unei clase ce nu are nici in clin nici in maneca cu o instanta a acelei clase?
A: NU.

Totusi, asemenea functii se gasesc in "the real programmers' life" si nu putine.
Sunt trei mari categorii de motive:
  1. nestiinta, lene, graba - toate scuzabile: nu se naste nimen invatat (C++ e un limbaj destul de dificil), sa scrii 'static' e destul de greu [ :) ] iar cu un deadline la **** tau se poate sa mai uiti.
  2. aplicarea unor principii, paradigme si patternuri intr-un design prost - daca, ca si developer, intrebi un un architect "de ce mama-mati ai pus o metoda non-statica intr-o clasa zeroton (parafaza la 'singleton')", ala o sa afiseze o mina afectata apoi va pune banda cu encapsulation, scalability, and so on. Din pacate, acum dai cu tunul sa gasesi un programator C++ care sa stie cat de cat cu ce se mananca o functie virtuala sau o functie in general dar de asemenea 'architects' te impiedici din juma in juma de metru.
  3. ne dam jmekeri la interviu - punem intrebari de 100 puncte ca sa stie lumea ca firma noastra-i tare in C++. Pana la urma angajam o blonda cu tzatze mari.
[ va urma ]

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Intrebare de interviu

Post by Ovidiu Cucu » 12 May 2011, 14:23

[ continuare ]

Q: Puteti da un exemplu practic in care apelarea unei metode non-statice printr-un pointer (posibil) NULL, are sens?
A: Da.
Exemplu:

Code: Select all

class A
{
   int* p;
public:
   A() : p(NULL) {}
   int* GetSafeP() {return (NULL == this) ? NULL : p;}
};

class CFoo
{
public: 
   void OnDoSomething(A* pA);
};

void CFoo::OnDoSomething(A* pA)
{
   int* p = pA->GetSafeP();
   //...
}
Q: La ce bun?
A: Tema pentru acasa. Mai ales pentru arhitecti. ;)

stackoverflow
Junior
Junior
Posts: 10
Joined: 12 May 2011, 12:16

Re: Intrebare de interviu

Post by stackoverflow » 12 May 2011, 15:13

Ovidiu Cucu wrote:[ continuare ]

Q: Puteti da un exemplu practic in care apelarea unei metode non-statice printr-un pointer (posibil) NULL, are sens?
A: Da.
Exemplu:

Code: Select all

class A
{
   int* p;
public:
   A() : p(NULL) {}
   int* GetSafeP() {return (NULL == this) ? NULL : p;}
};

class CFoo
{
public: 
   void OnDoSomething(A* pA);
};

void CFoo::OnDoSomething(A* pA)
{
   int* p = pA->GetSafeP();
   //...
}
Q: La ce bun?
A: Tema pentru acasa. Mai ales pentru arhitecti. ;)
Am incercat asta in Visual Studio si nu merge. Am mai adaugat asta:

Code: Select all

void main()
{
    A* test;
    int* p = test->GetSafeP();//aici crapa
}

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Intrebare de interviu

Post by Ovidiu Cucu » 12 May 2011, 15:30

stackoverflow wrote: Am mai adaugat asta:

Code: Select all

void main()
{
    A* test;
    int* p = test->GetSafeP();//aici crapa
}
Bineinteles ca (virgula) crapa.
Ia mai adauga asta:
A* test = NULL;
Mai crapa?

stackoverflow
Junior
Junior
Posts: 10
Joined: 12 May 2011, 12:16

Re: Intrebare de interviu

Post by stackoverflow » 12 May 2011, 15:32

Ovidiu Cucu wrote:
stackoverflow wrote: Am incercat asta in Visual Studio si nu merge. Am mai adaugat asta:

Code: Select all

void main()
{
    A* test;
    int* p = test->GetSafeP();//aici crapa
}
Bineinteles ca (virgula) crapa.
Ia mai adauga asta:
A* test = NULL;
Mai crapa?
Daca fac asta atunci cum mai e safe? Safe nu inseamna sa mearga indiferent daca initializez sau nu? Nu exact de asta ar trebui sa ma protejeze, de variabilele neinitializate sau de variabilele sterse si folosite dupa stergere?

Code: Select all

void main()
{
    A* test = new A();
    delete test;
    int* p = test->GetSafeP();//si aici crapa
}
[/quote]

Post Reply