PDA

Tam Sürümünü Görmek İçin : templates - friend to a global function


ankakusu
19/12/2006, 20:15
let me write the whole code explicitly:

AlgebraicExpression global bir fonksiyon. .h and .cpp kodlarini asagiya koydum. ve Stack.h ,Stack.cpp kodları var. AlgebraicExpression class'ının içinde kullanacağım Stakc'i ama 2 çeşit Stack kullanmam gerekiyor. Birinin çeşidi char olacak diğerininki de int. dolayısıyla template kullanıp. duruma göre özelliklerini değiştirmeye çalışacağım.

Soru:
Stack.h 'da şöyle yazdım:
friend class AlgebraicExpression;

ama yine de AlgebricExpression'dan Stack'ın içindeki private data memberlara ulaşamıyorum. Mesela topPtr diye bir pointer var Stack'ın içinde ona erişemiyorum. Bunu nasıl çözeceğim?


//AlgebraicExpression.h
#include <string>
using std::string;

#include "Stack.h"

string infix2postfix( const string);
int CheckTypeOfChar(const char);
int precedence(const char);
void toStack(const string );


Stack<char> operands;
Stack<int> operators; // end of AlgebraicExpression.h


//AlgebraicExpression.cpp

#include <iostream>
using std::cout;
using std::endl;

#include <string>
using std::string;

#include "AlgebraicExpression.h"

string infix2postfix( const string exp ){
string postFix=" ";
T tempc;
T tempi;

for(int index=0;index<exp.length();index++ ){
int ch=CheckTypeOfChar(exp[index]);
switch (ch)
{
case 1:
(int) exp[index];
operands.push(exp[index]);
break;
case 2:

while (!operators.isEmpty()&&operators.topPtr->item!='('&& precedence(ch) <= precedence(operators.topPtr->item)){
postFix += operators.topPtr->item;
operators.pop(tempc);
}
operators.push(exp[index]);
//postFix+=exp[index];
break;
case 3:
operators.push(exp[index]);
break;
case 4:
while ( operators.topPtr -> item != '('){
postFix += operators.topPtr -> item;
operators.pop(T);
//cout<< "operators.topPtr->item" <<operators.topPtr->item<<endl;
}
operators.pop();
//cout<< "operators.topPtr->item" <<operators.topPtr->item<<endl;
operators.push(exp[index]);
break;
}
}
return postFix;
}

int CheckTypeOfChar(const char ch){
if(ch =='1' || ch =='2'||ch =='3'||ch =='4'||ch =='5'||ch =='6'||ch =='7'||ch =='8'||ch =='9')
return 1;
else if (ch == '*' || ch =='/' || ch =='+' || ch =='-' )
return 2;
else if (ch == '(')
return 3;
else if ( ch ==')')
return 4;
}

int precedence (const char ch1){
char operatorTypes[]={'*','/','+','-','(',')'};
if(ch1==operatorTypes[0] || ch1==operatorTypes[1] )
return 2;
else if (ch1==operatorTypes[2] || ch1==operatorTypes[3] )
return 1;

}

void toStack(const string exp )
{
for(int index=0;index<exp.length();index++ )
{
int ch=CheckTypeOfChar(exp[index]);
switch (ch)
{
case 1:
(int) exp[index];
operands.push(exp[index]);
break;
case 2:
operators.push(exp[index]);
break;
case 3:
operators.push(exp[index]);
break;
case 4:
operators.push(exp[index]);
break;
}
}
};//end of AlgebraicExpression.cpp

//Stack.h
template < typename T>
class Stack
{
friend class AlgebraicExpression;

public:

Stack();
Stack(const Stack&);
~Stack();

bool isEmpty () const;
void push(T newItem);
void pop ();
void pop(T& stackTop);
void getTop(T& stackTop);

private:
struct StackNode
{
T item;
StackNode *next;
};

StackNode *topPtr;
int size;
};//end of Stack.h


//Stack.cpp
#include <cstddef>

#include "Stack.h"

template < typename T>
Stack<T>::Stack() : topPtr(NULL)
{
}
template < typename T>
Stack<T>::Stack(const Stack& aStack)
{
if (aStack.topPtr == NULL)
topPtr = NULL; // original list is empty

else
{ // copy first node

topPtr = new StackNode;
topPtr->item = aStack.topPtr->item;

// copy rest of list
StackNode *newPtr = topPtr; // new list pointer

for (StackNode *origPtr = aStack.topPtr->next;origPtr != NULL; origPtr = origPtr->next)
{ newPtr->next = new StackNode;
newPtr = newPtr->next;
newPtr->item = origPtr->item;
} // end for
newPtr->next = NULL;
} // end if
} // end copy constructor

template <class T>
Stack<T>::~Stack()
{
// pop until stack is empty
while (!isEmpty())
pop();
// Assertion: topPtr == NUL
} // end destructor

template <class T>
bool Stack<T>::isEmpty() const
{
return topPtr == NULL;
} // end isEmpty

template < typename T>
void Stack<T>::push(T newItem)
{
// create a new node
StackNode *newPtr = new StackNode;

// set data portion of new node
newPtr->item = newItem;
// insert the new node
newPtr->next = topPtr;
topPtr = newPtr;
} // end push

template <class T>
void Stack<T>::pop() //throw(StackException)
{
if (isEmpty());
//throw StackException("StackException: stack empty on pop");

else
{ // stack is not empty; delete top
StackNode *temp = topPtr;
topPtr = topPtr->next;
// return deleted node to system
temp->next = NULL; // safeguard
delete temp;
} // end if
} // end pop

template < typename T>
void Stack< T >::pop(T& stackTop) // throw(StackException)
{
if (isEmpty());
// throw StackException("StackException: stack empty on pop");

else
{ // stack is not empty; retrieve and delete top
stackTop = topPtr->item;
StackNode *temp = topPtr;
topPtr = topPtr->next;

// return deleted node to system
temp->next = NULL; // safeguard
delete temp;
} // end if
} // end pop

template < typename T>
void Stack<T>::getTop(T& stackTop) //const //throw(StackException)
{
if (isEmpty());
// throw StackException("StackException: stack empty on getTop");

else
// stack is not empty; retrieve top
stackTop = topPtr->item;
} // end getTop
// End of implementation file. end of Stack.cpp

//driver.cpp
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include <exception>
using std::exception;

#include <string>
using std::string;
using std::strncat;

#include <cstddef>

#include "AlgebraicExpression.h"

int main(){
cout<<infix2postfix("3+4+5");
return 0;
};//end of driver.cpp
Hata:

AlgebraicExpression.cpp: In function 'std::string infix2postfix(std::string)':
AlgebraicExpression.cpp:12: error: 'T' was not declared in this scope
AlgebraicExpression.cpp:12: error: expected `;' before 'tempc'
AlgebraicExpression.cpp:13: error: expected `;' before 'tempi'
Stack.h:25: hata: 'Stack<int>::StackNode* Stack<int>::topPtr' is private
AlgebraicExpression.cpp:25: error: bu baglamda
Stack.h:25: hata: 'Stack<int>::StackNode* Stack<int>::topPtr'is private
AlgebraicExpression.cpp:25: error: bu baglamda
Stack.h:25: hata: 'Stack<int>::StackNode* Stack<int>::topPtr' is private
AlgebraicExpression.cpp:26: error: bu baglamda
AlgebraicExpression.cpp:27: error: 'tempc' was not declared in this scope
Stack.h:25: hata: 'Stack<int>::StackNode* Stack<int>::topPtr' is private
AlgebraicExpression.cpp:36: error: bu baglamda
Stack.h:25: hata: 'Stack<int>::StackNode* Stack<int>::topPtr' is private
AlgebraicExpression.cpp:37: error: bu baglamda


acehreli
19/12/2006, 20:42
AlgebraicExpression sinifini gostermemissin; ben bir tane uydurdum.

Ayrica, AlgebraicExpression'in Stack'le ayni tUrden olanina mi yoksa her tUrUne mi ozel erisim vermek istedigini de bilmiyorum. Yani AlgebraicExpression<double> Stack<int>'e erisebilsin mi?

Onun icin ikisinin de ornegini verdim:



#include <iostream>
#include <ostream>

// Stack icinde belirli bir tUrunden bahsedecegimiz icin
// AlgebraicExpression'i onceden bildirmemiz gerekiyor:
template < typename T>
class AlgebraicExpression;

template < typename T>
class Stack
{
private:

// Yalnizca ayni tUrden (T) AlgebraicExpression'i friend yapiyoruz
friend class AlgebraicExpression<T>;

// Bu sinif sablonunun ise her tUrUnU friend yapiyoruz; bu satir ayni
// zamanda BaskaBirTur'un bu noktadaki bir bildirimi oluyor.
template <typename TT> friend class BaskaBirTur;

int size;

public:

void yazdir() const
{
std::cout << size << '\n';
}
};

template < typename T >
class AlgebraicExpression
{
public:

void foo(Stack<T> & stack, int deger)
{
stack.size = deger;
}
};

template <typename T>
class BaskaBirTur
{
public:

template <typename T>
void foo(Stack<T> & stack, int deger)
{
stack.size = deger;
}
};

int main()
{
Stack<int> s;

// s ile ayni tUrden (int)
AlgebraicExpression<int> ae;
// Ozel uyeye erisim
ae.foo(s, 42);
s.yazdir();

// Baska tUrden olunca erisemez:
/*
* AlgebraicExpression<double> aed;
* aed.foo(s, 43); // <-- DERLEME HATASI
* s.yazdir();
*/

// s'den baska bir tUrden (double)
BaskaBirTur<double> b;
// Ozel uyeye erisim
b.foo(s, 44);
s.yazdir();
}


Ali

ankakusu
19/12/2006, 22:32
Merhaba Ali,
Aslinda AlgebraicExpression.h ve AlgebraicExpression.cpp oradalar. İlk iki kod. Sanirim ben kodlarin ne ise yaradigini anlatamadim.

Simdi AlgebraicExpression diye bir fonksiyon var. (hata bende bunun icin class demistim sanirim. ) bu global bir fonksiyon. infix bir islemi postfix haline cevirme islemini yapmaya calisiyorum ilk etapta. ( infix: "3+5/2" gibi bir islem oluyor. Yani toplama, cikarma, bolme gibi islemler rakamlarin arasinda oluyor. Bunu postfix yapmaya calisiyorum:

"35+5/" (*)

bunun anlami su; soldan saga dogru islemleri gerceklestiriyorum. yani once 3 ile 5'i topla.
35+ = 8 demek.yukarida 35+ yerine 8 yazacagim. simdi (*) denklemi su hali aldi:

85/

bu da 8'i al 5'e bol demek oluyor.

AlgebraicExpression.cpp'deki infix2postFİx bu ise yariyor ama eksikleri var tabii ki. su hatalari cozebilirsem geri kalanini halletmeye calisacagim.

Bunu cozmek icin Stack kullanacagim. islemler (operators ) icin char Stack'ini kullanmak istiyorum. rakamlar(operands) icin de int Stack'i kullanmak istiyorum. Stack'i template yapmaya calistim o yuzden.

AlgebraicExpression.h'ta

Stack<char> operands;
Stack<int> operators;


diye degiskenler yarattim. AlgebraicExpression.cpp'de de kullanacagim. sanirim burada bir hata vermiyor ama Stack.h'taki topPtr pointer'ina erismeye calisirken sorun yasiyorum bunu bir turlu anlamadim...

Sabahi
19/12/2006, 22:54
ilk etapta. ( infix: "3+5/2" gibi bir islem oluyor. Yani toplama, cikarma, bolme gibi islemler rakamlarin arasinda oluyor. Bunu postfix yapmaya calisiyorum:

"35+5/" (*)

bunun anlami su; soldan saga dogru islemleri gerceklestiriyorum. yani once 3 ile 5'i topla.
35+ = 8 demek.yukarida 35+ yerine 8 yazacagim. simdi (*) denklemi su hali aldi:

85/

bu da 8'i al 5'e bol demek oluyor.

Kodunuza bakmaya zamanim olmadi henuz ama infix 3+5/2 isleminin postfix e donusumunu yanlis yapiyorsunuz gibi geldi. Infix ifadelerde bolme ve carpma daha oncelikli islemlerdir. Soldan sagada gitseniz once bolmeyi sonra toplamayi yapmaniz gerekirdi diye dusunuyorum.
Infix: 3 + 5 / 2 -> Postfix: 5 2 / 3 +

ankakusu
19/12/2006, 22:58
MErhaba,
Ben biraz acemi sayilirim programlama konusunda. Sİmdi yukaridaki acehreli'nin yazdiklarini oldugu gibi bir dosyaya kopyalayip compile etmeye calistim ama bir suru hata veriyor. mesela en basta:

mesela:

Stack.cpp:47: hata: declaration of 'class T'
Stack.cpp:42: hata: shadows template parm 'class T'

bunlar ne demek? sanırım boyle ayrintilari anlayamadan kendimi gelistirmem biraz zor olacak.

ankakusu
19/12/2006, 23:02
Kodunuza bakmaya zamanim olmadi henuz ama infix 3+5/2 isleminin postfix e donusumunu yanlis yapiyorsunuz gibi geldi. Infix ifadelerde bolme ve carpma daha oncelikli islemlerdir. Soldan sagada gitseniz once bolmeyi sonra toplamayi yapmaniz gerekirdi diye dusunuyorum.
Infix: 3 + 5 / 2 -> Postfix: 5 2 / 3 +


evet dogru diyorsun. biliyorum. simdi hizli hizli yazdigim icin oyle yanlis yazmisim. islemlerin onceliklerine dikkat etmemisim. ama benim burada sormak istedigim bazi temel noktalari nasil cozmem gerektigi. Orada mesela private topPtr'i bir turlu kullanamıyorum. bunu nasıl çözmem gerek.

daha önce de dediğim gibi. bazı temel noktalarda problemlerim olduğu için programlamanın mantığını anlamakta zorlanıyorum..

Sabahi
19/12/2006, 23:22
Neden class identifier kullaniyorsun eger Algebric expression tek basina bir fonksiyon ise?

friend class AlgebraicExpression; ???

Bu arada hem global fonksiyon hemde class ayni isimde mi?

Genelde herhangi bir fonksiyonu friend yapmak icin class tanimida:

friend void foo(); gibi oluyor yanilmiyorsam.

ankakusu
19/12/2006, 23:56
bu konuda da haklısın.

bir sey sormak istiyorum.

Global fonksiyonlar su demek sanirim: herhangi bir class icinde tanimlanmiyorlar ve herhangi bir class bu fonksiyonlara hemen erisebiliyor.

sorum su:

Peki Global Class diye bir sey var mi? yani varsa benim yazdigim AlgebraicExpression.h ve .cpp global class olabilir mi? MEsela ben Stack'in icindeki topPtr'a ulasmak istiyorum o zaman Stack'in neyi ve kimi arkadas olarak benimsemesi gerek ki ben AlgebraicExpression'dan topPtr'a ulasabileyim?

acehreli
20/12/2006, 01:32
ankakusu, oncelikle, ilgimizi koruyabilecegimizden fazla kod veriyorsun. O kadar kodun icinden cikivermek kolay degil. Onun icin ilk mektubumda yalnizca sordugun soruyu yanitladim. Bazi notlar:

1) Aldigin derleme hatasinin hangi derleyicide oldugundan emin degilim. Benim derleyicim derleyince farketmemisim demek ki... Sanirim derleme hatasini soyle giderebilirsin:


template <typename T>
class BaskaBirTur
{
public:

/*
Burada T yerine TT (veya baska bir ad) kullan:
*/
template <typename TT>
void foo(Stack<TT> & stack, int deger)
{
stack.size = deger;
}
};


Eger hata orada degilse, ona benzer bir yerdedir.

2) C++ standart kutuphanesinde zaten std::stack diye bir tUr var; onu kullanmak isteyebilirsin

3) Eger Stack'in ozel bir ogesine erismek istiyorsan bir seyleri yanlis yapiyorsun demektir. Sarmada (encapsualtion) amac, bir sinifin hizmetlerini arayuzu yoluyla sunmaktir. Isini Stack'in push, pop, ve getTop islevleriyle halledebilirsin (halletmelisin).

4) Arkadaslik kavramindan olabildigince uzak durmaya bak. O, bir toplulugun erisicileriyle arasindaki (containers and iterators) veya bir listenin dugumleriyle arasindaki (lists and nodes) gibi yakin iliskilerde kullanmaya elverislidir.

Ali

Sabahi
20/12/2006, 01:35
Peki Global Class diye bir sey var mi? yani varsa benim yazdigim AlgebraicExpression.h ve .cpp global class olabilir mi?
Global Class diye bir kavram duymadim. Aslinda sizin kullandiginiz sekli ile bir fonksiyona global diye bir tanimlama getirmek de pek dogru olmasa gerek. Global fonksiyon denince benim aklima gelen abs() gibi kutuphanelerle gelen bir fonksiyon.
Bu arada programinizin icerisinde hic bir yerde AlgebraicExpression diye bir fonksiyon tanimida goremedim.
Anladigim kadari ile stack zaten abstract bir data type olarak tanimlanmis bu durumda neden stack'in uyelerine direk ulasmak istiyorsunuz? Dikkat ettiyseniz stack item type T olarak tanimlanmis. Yani char yada int push yapmak icin ayri bir caba gostermenize gerek yok.

ankakusu
20/12/2006, 03:39
template <typename T>
class BaskaBirTur
{
public:

/*
Burada T yerine TT (veya baska bir ad) kullan:
*/
template <typename TT>
void foo(Stack<TT> & stack, int deger)
{
stack.size = deger;
}
};
Eger hata orada degilse, ona benzer bir yerdedir.

Ali

evet o zaman calisti :) ama neden ? class BaskaBirTur'un ustunde tanimladik template<T> diye sonra da icindeki fonksiyonu tanimlarken, bu sefer template<TT> olacak sekilde tanimladik.

burada BirBaskaTur class'ini cok type'li olarak tanimlamak islevi Stack class'i icerisindeki friend tanimlamasindan kaynaklaniyor degil mi?

ankakusu
20/12/2006, 03:44
Yani char yada int push yapmak icin ayri bir caba gostermenize gerek yok.

hmm.. tam olarak ne demek istediginizi anlamadim. AlgebraicExpression class'inda 2 cesit Stack objesi yaratmak istiyorum birincisi char type'inda olacak digeri de int type'inda.

zaten bi T type yaratmamizin nedeni bu degil mi? farki cesitlerde Stack objeleri kullanabilmek boylece elimizde daha esnek bir sinifimiz olmus olacak?

ankakusu
20/12/2006, 04:11
bir de bir ricam olacak acaba burada template'in tam olarak ne oldugunu anlatabilir misiniz acaba?

Sabahi
20/12/2006, 04:56
hmm.. tam olarak ne demek istediginizi anlamadim. AlgebraicExpression class'inda 2 cesit Stack objesi yaratmak istiyorum birincisi char type'inda olacak digeri de int type'inda.

zaten bi T type yaratmamizin nedeni bu degil mi? farki cesitlerde Stack objeleri kullanabilmek boylece elimizde daha esnek bir sinifimiz olmus olacak?
acehrelinin cevabini gec farkettim. Onun 3 numarali aciklamasindakine benzer bir sey soylemek istemistim ama ifade etmekte oldukca yetersiz kalmisim:)
Ben kafanizi karistirmaktansa bu konuda yorum yapmayi acehreliye birakayim gayet guzel anlatiyor.

acehreli
20/12/2006, 20:15
ankakusu, birinci sorunun yaniti su: "T" adini BaskaBirTur'un taniminda sablon (template, shablon, $ablon, vs.) parametresi olarak kullandigim halde, onun icindeki foo islevinin sablon parametresi olarak da "T" kullanmisim. foo'nun parametresinin adini "TT" yapinca karisiklik ortadan kalkmis oldu.

BirBaskaTur'u neden sablon olarak tanimladigimi soruyorsun. Bir nedeni yok, yalnizca bir sablon sinifin (BirBaskaTur) nasil baska bir sablon sinifin (Stack) dostu yapildigini gostermek istemistim.

Sablonlar gunluk kullanimlarinda aslinda cok kolaydirlar. Onun otesine gecince isler karmasiklasir. Sablonlar (templates) hakkinda kucuk bir yazi yazmistim:

http://ceviz.net/index.php?case=article&id=170&catid=13

Su sayfada sablonlari kullanan baska yazilar da bulabilirsin:

http://ceviz.net/index.php?case=category&id=13

Oradaki diger yazilar sablonlara bir sekilde deginirler. Su sirada okumak yararli olabilir:

Turden bagimsiz bir toplama algoritmasi
C++'in turden bagimsiz topluluklari
std::vector temel islemleri
std::vector ileri duzey islemleri
std::map ve std::multimap
Islev nesneleri
Akilli gostergeler
Boost akilli gostergeleri

Ali

acehreli
20/12/2006, 20:20
Simdi baktigimda o sayfada bozukluklar oldugunu farkettim. Hem 'son'un sayilarin disinda kaldigini soyledigim yerde bir gosterim hatasi var, hem de ornek kodlardan birisi eksik cikmis.

Ayni yazinin baska bir kopyasi surada:

http://acehreli.org/turkcecpp/turden_bagimsiz_toplama.html

Ali

ankakusu
22/12/2006, 04:22
merhaba oncelikle tesekkur ederim. Bir de sitede her şey Türkçe çevirileriyle beraber veriliyor, bu gerçekten çok faydalı oldu. Bunun için de ayrıca teşekkür ederim.

Bir sorum olacaktı:


void merhaba(ostream & cikis,
string const & soz,
string const & kim)
{
cikis << soz << ' ' << kim << "!
";
}


burada çıktıyı gönderirken hiç cout kullanmamışız. 'ostream & cikis' tam olarak ne yapiyor? bir şeyin türü ostream olduğu zaman cout kullanmaya gerek kalmıyor mu?

bir sorum daha olacaktı. Türkçesini bilmiyorum ama 'dynamic memory management' hakkında bir yazı var mı buralarda? beni yönlendirebilir misiniz?

ankakusu
22/12/2006, 04:42
bu hatanın nedeni ne acaba bir şekilde AlgebraicExpression Stack'in fonksiyonlarını göremiyor.




//AlgebraicExpression.h

#include <string>
using std::string;

#include "Stack.h"

string infix2postfix( const string);
int CheckTypeOfChar(const char);
int precedence(const char);
void toStack(const string );


Stack<char> operands;
Stack<int> operators;





//AlgebraicExpression.cpp

#include <iostream>
using std::cout;
using std::endl;

#include <string>
using std::string;

#include "AlgebraicExpression.h"

string infix2postfix( const string exp ){
string postFix=" ";

for(int index=0;index<exp.length();index++ ){
int ch=CheckTypeOfChar(exp[index]);
switch (ch)
{
case 1:
(int) exp[index];
operands.push(exp[index]);
break;
case 2:

while (!operators.isEmpty()&&operators.getTopPtr()!='('&& precedence(ch) <= precedence(operators.getTopPtr())){
postFix += operators.getTopPtr();
operators.pop();
}
operators.push(exp[index]);
//postFix+=exp[index];
break;
case 3:
operators.push(exp[index]);
break;
case 4:
while ( operators.getTopPtr() != '('){
postFix += operators.getTopPtr() ;
operators.pop();

}
operators.pop();

operators.push(exp[index]);
break;
}
}
return postFix;
}

int CheckTypeOfChar(const char ch){
if(ch =='1' || ch =='2'||ch =='3'||ch =='4'||ch =='5'||ch =='6'||ch =='7'||ch =='8'||ch =='9')
return 1;
else if (ch == '*' || ch =='/' || ch =='+' || ch =='-' )
return 2;
else if (ch == '(')
return 3;
else if ( ch ==')')
return 4;
}

int precedence (const char ch1){
char operatorTypes[]={'*','/','+','-','(',')'};
if(ch1==operatorTypes[0] || ch1==operatorTypes[1] )
return 2;
else if (ch1==operatorTypes[2] || ch1==operatorTypes[3] )
return 1;

}

void toStack(const string exp )
{
for(int index=0;index<exp.length();index++ )
{
int ch=CheckTypeOfChar(exp[index]);
switch (ch)
{
case 1:
(int) exp[index];
operands.push(exp[index]);
break;
case 2:
operators.push(exp[index]);
break;
case 3:
operators.push(exp[index]);
break;
case 4:
operators.push(exp[index]);
break;
}
}
};





//Stack.h

template < typename T>
class Stack
{
public:
struct StackNode
{
T item;
StackNode *next;
};


Stack();
Stack(const Stack&);
~Stack();

bool isEmpty () const;
void push(T newItem);
void pop ();
void pop(T& stackTop);
void getTop(T& stackTop);
T getTopPtr();

private:
StackNode *topPtr;
int size;
};






//Stack.cpp

#include <cstddef>

#include "Stack.h"

template < typename T>
Stack<T>::Stack() : topPtr(NULL)
{
}
template < typename T>
Stack<T>::Stack(const Stack& aStack)
{
if (aStack.topPtr == NULL)
topPtr = NULL; // original list is empty

else
{ // copy first node

topPtr = new StackNode;
topPtr->item = aStack.topPtr->item;

// copy rest of list
StackNode *newPtr = topPtr; // new list pointer

for (StackNode *origPtr = aStack.topPtr->next;origPtr != NULL; origPtr = origPtr->next)
{ newPtr->next = new StackNode;
newPtr = newPtr->next;
newPtr->item = origPtr->item;
} // end for
newPtr->next = NULL;
} // end if
} // end copy constructor

template <class T>
Stack<T>::~Stack()
{
// pop until stack is empty
while (!isEmpty())
pop();
// Assertion: topPtr == NUL
} // end destructor

template <class T>
bool Stack<T>::isEmpty() const
{
return topPtr == NULL;
} // end isEmpty

template < typename T>
void Stack<T>::push(T newItem)
{
// create a new node
StackNode *newPtr = new StackNode;

// set data portion of new node
newPtr->item = newItem;
// insert the new node
newPtr->next = topPtr;
topPtr = newPtr;
} // end push

template <class T>
void Stack<T>::pop() //throw(StackException)
{
if (isEmpty());
//throw StackException("StackException: stack empty on pop");

else
{ // stack is not empty; delete top
StackNode *temp = topPtr;
topPtr = topPtr->next;
// return deleted node to system
temp->next = NULL; // safeguard
delete temp;
} // end if
} // end pop

template < typename T>
void Stack< T >::pop(T& stackTop) // throw(StackException)
{
if (isEmpty());
// throw StackException("StackException: stack empty on pop");

else
{ // stack is not empty; retrieve and delete top
stackTop = topPtr->item;
StackNode *temp = topPtr;
topPtr = topPtr->next;

// return deleted node to system
temp->next = NULL; // safeguard
delete temp;
} // end if
} // end pop

template < typename T>
void Stack<T>::getTop(T& stackTop) //const //throw(StackException)
{
if (isEmpty());
// throw StackException("StackException: stack empty on getTop");

else
// stack is not empty; retrieve top
stackTop = topPtr->item;
} // end getTop
// End of implementation file.
template <typename T>
T Stack<T>::getTopPtr (){
return topPtr->item;
}







//driver.cpp

#include <exception>
using std::exception;

#include <string>
using std::string;
using std::strncat;

#include <cstddef>

#include "AlgebraicExpression.h"

int main(){
cout<<infix2postfix("3+4+5");
return 0;
};




hata:



/tmp/ccZqKK3w.o:(.bss+0x0): `operators' i\u00e7in birden fazla tan\u0131m
/tmp/ccPr00h1.o:(.bss+0x0): ilk burada tan\u0131mlanm\u0131\u015f
/tmp/ccZqKK3w.o:(.bss+0x8): `operands' i\u00e7in birden fazla tan\u0131m
/tmp/ccPr00h1.o:(.bss+0x8): ilk burada tan\u0131mlanm\u0131\u015f
/tmp/ccPr00h1.o: In function `infix2postfix(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':AlgebraicExpression.cpp:(.text+0x20d): undefined reference to `Stack<char>::push(char)'
:AlgebraicExpression.cpp:(.text+0x21e): undefined reference to `Stack<int>::getTopPtr()'
:AlgebraicExpression.cpp:(.text+0x23c): undefined reference to `Stack<int>::pop()'
:AlgebraicExpression.cpp:(.text+0x248): undefined reference to `Stack<int>::isEmpty() const'
:AlgebraicExpression.cpp:(.text+0x25c): undefined reference to `Stack<int>::getTopPtr()'
:AlgebraicExpression.cpp:(.text+0x27e): undefined reference to `Stack<int>::getTopPtr()'
:AlgebraicExpression.cpp:(.text+0x2cc): undefined reference to `Stack<int>::push(int)'
:AlgebraicExpression.cpp:(.text+0x2f9): undefined reference to `Stack<int>::push(int)'
:AlgebraicExpression.cpp:(.text+0x307): undefined reference to `Stack<int>::getTopPtr()'
:AlgebraicExpression.cpp:(.text+0x325): undefined reference to `Stack<int>::pop()'
:AlgebraicExpression.cpp:(.text+0x331): undefined reference to `Stack<int>::getTopPtr()'
:AlgebraicExpression.cpp:(.text+0x347): undefined reference to `Stack<int>::pop()'
:AlgebraicExpression.cpp:(.text+0x36f): undefined reference to `Stack<int>::push(int)'
/tmp/ccPr00h1.o: In function `toStack(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':AlgebraicExpression.cpp:(.text+0x462): undefined reference to `Stack<char>::push(char)'
:AlgebraicExpression.cpp:(.text+0x48c): undefined reference to `Stack<int>::push(int)'
:AlgebraicExpression.cpp:(.text+0x4b6): undefined reference to `Stack<int>::push(int)'
:AlgebraicExpression.cpp:(.text+0x4e0): undefined reference to `Stack<int>::push(int)'
/tmp/ccPr00h1.o: In function `__tcf_1':AlgebraicExpression.cpp:(.text+0x52e): undefined reference to `Stack<char>::~Stack()'
/tmp/ccPr00h1.o: In function `__tcf_2':AlgebraicExpression.cpp:(.text+0x542): undefined reference to `Stack<int>::~Stack()'
/tmp/ccPr00h1.o: In function `__static_initialization_and_destruction_0(int, int)':AlgebraicExpression.cpp:(.text+0x597): undefined reference to `Stack<char>::Stack()'
:AlgebraicExpression.cpp:(.text+0x5bf): undefined reference to `Stack<int>::Stack()'
/tmp/ccZqKK3w.o: In function `__tcf_1':driver.cpp:(.text+0x10e): undefined reference to `Stack<char>::~Stack()'
/tmp/ccZqKK3w.o: In function `__tcf_2':driver.cpp:(.text+0x122): undefined reference to `Stack<int>::~Stack()'
/tmp/ccZqKK3w.o: In function `__static_initialization_and_destruction_0(int, int)':driver.cpp:(.text+0x177): undefined reference to `Stack<char>::Stack()':driver.cpp:(.text+0x19f): undefined reference to `Stack<int>::Stack()'
collect2: ld \u00e7\u0131k\u0131\u015f durumu 1 ile d\u00f6nd\u00fc

acehreli
22/12/2006, 11:12
ostream cikis akimidir. cout ise olasi sonsuz cikis akimindan yalnizca bir tanesidir. Dosyalar cikis akimlari olabilirler, ostringstream nesneleri cikis akimi olabilirler, kendimiz ozel cikis akimlari tasarlayabiliriz, vs. cout'un bir ayricaligi yoktur.

Orada 'merhaba' islevi daha kullanisli olsun diye karakterleri cout'a degil, kendisine verilen cikis akimina gonderiyor. Su programi dene:

#include <iostream>
#include <ostream>
#include <string>
#include <fstream>

using namespace std;

void merhaba(ostream & cikis,
string const & soz,
string const & kim)
{
cikis << soz << ' ' << kim << "!";
}

int main()
{
// merhaba'yi cout ile kullanabiliriz:
merhaba(cout, "Merhaba", "Ali");

// Ama baska bir akimla da kullanabiliriz:
const char * dosyaAdi = "benim_cikis_dosyam.txt";
ofstream dosya(dosyaAdi);
merhaba(dosya, "Selam", "Veli");

cout << "\nSimdi " << dosyaAdi << " adli dosyanin icine bak!";
}

Belki << islecinin kullanilmis olmasi seni yaniltmis olabilir. Eger oyleyse, << isleci cout'a ozel degildir. O islec her cikis akimiyla calisir.

Derleme hatasi da baslik dosyasinda nesne tanimladigin icin oluyor. Baslik dosyasi birden fazla cpp dosyasina eklenince, baslik dosyasindaki nesne butun o dosyalar tarafindan tanimlanmis oluyor. (#include etmek, basliktaki butun yazilari #inlude edilen yere almaktir.)

Bunun cozumu, nesneyi baslik dosyasinda "bildirmek" (declare) ve tek bir cpp dosyasinda "tanimlamaktir" (define):


// Baslik dosyasinda:
extern Stack<int> operators;



// Tek bir cpp dosyasinda:
Stack<int> operators;


Bunu 'operands' icin de yapman gerekecek.

Ali