• Sonuç bulunamadı

Ne zaman operatör aşırı yükleme yapılır. Aşırı Yüklenebilen C++ Operatörleri. Aşırı Yüklenemeyen Operatörler

N/A
N/A
Protected

Academic year: 2022

Share "Ne zaman operatör aşırı yükleme yapılır. Aşırı Yüklenebilen C++ Operatörleri. Aşırı Yüklenemeyen Operatörler"

Copied!
13
0
0

Yükleniyor.... (view fulltext now)

Tam metin

(1)

11/8/2007 Nesneye Yonelik Programlama 8.1

Opertörlerin Aşırı Yüklenmesi Operator Overloading

• Operatörün aşırı yüklenmesi; bir operatöre standart anlamı dışında yeni anlamlar kazandırmak anlamına gelir.

• Aşırı yüklenmiş operatör giriş olarak aldığı operandın (parametrelerin ) tipine göre anlam kazanır:

Örnek: standard matematikte, + ve – integers, reals, vectors, complex numbers, matrices, vb için tanımlanır.

C++ da, << operatorü aşırı yüklenmiştir.

1. Anlamı: akış çıkış operatörü - stream insertion operator 2. Anlamı: biteşlem sola kaydırma operatörü - Bitwise left-shift

operator

11/8/2007 Nesneye Yonelik Programlama 8.2

Ne zaman operatör aşırı yükleme yapılır

• Operatör aşırı yüklenmesi fonksiyon çağrılması ve üye fonksiyon çağırmaların notasyonunu kolaylaştırır:

Örnek: Color3 = mix (Color1, Color2); // yerine Color3= Color1 + Color2; // yazılabilir

burada

“+” color

lar için tanımlanmıştır.

• Operatör aşırı yüklenmesi aynı zamanda kullanıcı tarafından tanımlanmış yeni tiplerle hali hazırda var olan tipler arasındaki benzerliği pekiştirmek için kullanılırlar

Örnek: << ve >> operatörleri kullanıcı tanımlı tipler için çıktı/girdi işlemleri için tanımlanabilir.

Aşırı Yüklenebilen C++ Operatörleri

• Assignment operator ve stream operators

=, <<, >>

• Arithmetic operators

+, -, *, /, %, +=, -=, *=, /=, %=

• Increment and decrement operators

++, --

• Logical operators

!, &&, ||, <<, >>

• Bitwise logical operators

~, ^, &, |, ^=, &=, |=

• Relational and equality operators

<, >, <=, >=, ==, !=

• Dynamic memory allocation operators

new, delete, new [ ], delete [ ]

• Other operators

( ), [ ], ->, the comma operator ( , )

Aşırı Yüklenemeyen Operatörler

• . Dot member access operator

• .* Dot member access using pointer

• :: scope resolution operator

• ?: ternary conditional operator

• sizeof

(2)

11/8/2007 Nesneye Yonelik Programlama 8.5

C++ da operatörler nasıl aşırı yüklenir.

Yazım:

<return_type> <class_name>::operator#(<parameters>){

<function body that defines operator “#”>

} Anlamı:

• Operator # kullanıcının tanımladığı sınıfların (ismi class_name) nesneleri için yeniden tanımlanır.

• <parameters> tipik olarak <class_name> tipinde bir giris parametresi ve <return_type> tipik olarak <class_name> tipinde geri dönen değerin tipini gösterir.

11/8/2007 Nesneye Yonelik Programlama 8.6

Örnek

// Contents of the header file “point.h”

class Point { public:

// define a default constructor Point (int i=0, int j=0, int k=0 ) {

setPoint (i,j,k);

}

Point operator+ ( Point p) ; Point operator= (Point p);

void displayPoint () const;

void setPoint (int, int, int);

private:

int x,y,z; // 3-D coordinates };

// start of file “point.cpp”

#include <iostream>

#include “point.h”

void Point::setPoint (int i, int j, int k) { x = i;

y = j;

z = k;

}

void Point::displayPoint ( Point p) const { cout << “(“ << x

<< “, “ << y

<< “, “ << z

<< “)”;

}

Point Point::operator+ (Point p) { Point result;

result.x = x + p.x;

result.y = y + p.y;

result.z = z + p.z;

return result;

}

Point Point::operator= (Point p) { x = p.x;

y = p.y;

z = p.z;

return *this;

}

(3)

11/8/2007 Nesneye Yonelik Programlama 8.9

#include “point.h”

int main ( ) {

Point a (3,2,1), b(13,14,15), c;

a.displayPoint ( );

b.displayPoint ( );

c = a + b;

c.displayPoint ( );

c = a + b + c;

c.displayPoint ( );

c = b = a;

c.displayPoint ( );

b.displayPoint ( );

return 0;

}

11/8/2007 Nesneye Yonelik Programlama 8.10

Operatör aşırı yüklemede kısıtlamalar

• Operatör yüklemeyle operatörlere hali hazırda var olan tiplerdeki davranışlarıdan farklı bir davranış

kazandırılamaz.

• Operatör en az bir tane kullanıcı tanımlı tip veya sınıfı argüman olarak almalıdır.

• Operatör aşırı yüklemesi kapalı şekilde yapılamaz:

™ # operatörünü aşırı yüklemek # = operatörünün de aşırı yüklemek anlamına gelmez.

™ == operatörünü aşırı yüklemek != operatörünün de aşırı yüklemek anlamına gelmez.

Hint: ilgili bir kaç operatörü aşırı yüklemek istersek, her birini açık bir şeklide ayrı ayrı aşırı yüklemek gerekir.

• Aşırı yükleme parametre sayısını değiştiremez.

(4)

11/8/2007 Nesneye Yonelik Programlama 8.13 11/8/2007 Nesneye Yonelik Programlama 8.14

C++ << ve >> ye nasıl davranır?

• C++ derleyicisi cout << phone ile karşılaştığında, bunu fonksiyon çağrımı

operator << (ostream &, const PhoneNumber &) yazılışına dönüştürür.

• Sonuç sonraki çıktı argümanları kabul eden ostream dir ( << left associative).

• C++ derleyicisi cin >> phone ile karşılaştığında, bunu fonksiyon çağrımı

operator>>(istream &, PhoneNumber &) yazılışına dönüştürür.

• Sonuç daha sonraki girdi argümanlarını kabul eden istream dir ( >> left

associative ).

(5)

11/8/2007 Nesneye Yonelik Programlama 8.17

• Complex sınıfı için extraction operatörünün (>>) aşırı yüklü olduğunu varsayalım:

istream &operator >> (istream &input, Complex &cnum) {

input >> cnum.real >> cnum.imag;

return input;

}

• Aşırı yüklemiş operatör şu şekilde kullanılabilir:

Complex c_obj;

cin >> c_obj;

İkinci ifade cin >> c_obj; aşağıdaki ifadeye eşittir.

operator>> (cin, c_obj );

ve çalıştırıldığında ise

cin >> c_obj.real >> c_obj.imag;

ifadesine eşittir.

11/8/2007 Nesneye Yonelik Programlama 8.18

• Her iki parametre de referansla iletilir:

– Sistem stream lar hakkında bir takım bilgileri update ettiğinden dolayı, stream nesneleri daima reference ile fonksiyona iletilir veya geçirilir.

– İkinci nesnenin (Complex object) veri üyeleri update edildiğinden fonksiyona referansla geçirilir.

• Stream referans olarak geri döndürülür. Böylece input (output) operatörlerini ardı sıra tekrarlı olarak kullanabiliriz (cascade).

Complex c1_obj, c2_obj;

cin >> c1_obj >> c2_obj;

• Single call (tekli öçağrım) olarak kullanıldığında:

cin >> c_obj;

Döndürülen değer kullanılmaz. İkinci arguman c_obj birinci argümana göre değiştirilir.

• Zincirli bir şekilde çağrım yapıldığında:

cin >> c1_obj >> c2_obj;

İkinci argüman c1_obj birinci argüman cin e göre değiştirilir ve döndürülen değer ikinci fonksiyon çağrımı için ilk argüman görevini görür

operator >> (input, c2_obj );

Buradaki input c1_obj nin değerini içeren istream nesnesidir.

Unary Operatör Aşırı Yüklemesi

• Tek argümanlı (Unary) operatörlerin aşırı yüklemesinin iki yolu vardır:

– Argümansız non-static member fonksiyonu kullanarak (nesne argüman olarak davranır)

Örnek:

class String { public:

bool operator!() const;

...

};

– Bir argümanlı non-member fonksiyonu kullanarak (argüman nesne veya nesneye referana olmalıdır)

Örnek:

class String {

friend bool operator! (const String &) ...

(6)

11/8/2007 Nesneye Yonelik Programlama 8.21

İkili Operatörlerin Aşırı Yüklenmesi

• İkili (binary) operatörlerin aşırı yüklenmesi için iki yöntem vardır:

– Bir arguümanlı non-static üye fonksiyon kullanarak (nesne ikinci argüman olarak davranır)

class String { public:

const String &operator+= ( const String & );

...

};

– İki argümanlı bir üye olmayan fonksiyon kullanarak (argümanlardan bir tanesi nesne veya nesneye referans olmalıdır).

class String {

friend const String &operator+=(String &, const String &) ...

};

11/8/2007 Nesneye Yonelik Programlama 8.22

Kopya Yapıcı ve Atama Operatörleri Copy Constructors & Assignment Operators

• Varsayılan olarak, bir nesne ataması yapıldığında veya nesnenin kopyası gerektiğinde, karşılıklı elemanlar arası kopyalama (memberwise copy) kullanılarak kopyalama işlemi gerçekleştirilir.

• Eğer nesneler dinamik olarak tahsis edilen bellek alanlarına sahip ve kopya yapıcısı yoksa hafıza ile ilgili problemler ortaya çıkar:

– Bir kopyayı yok etmek tahsis edilen hafızanın silinmesi anlamına gelir ve diğer nesneler tarafından işaret edilen hafıza alanının da yok edilmesi anlamına gelir.

• Çözüm: dinamik olarak tahsis edilen nesnelerinin

kopyasını oluşturmak için bir kopya yapıcı ve bir aşırı

yüklenmiş atama operatörü tanımlamaktır.

(7)

11/8/2007 Nesneye Yonelik Programlama 8.25

Copy Constructors

• Sınıf deklerasyonunda,

<class_name> (const <class_name> &) eklenmelidir.

• Yeni üye fonksiyonun tanımlanması:

– (1) dinamik olarak var edilen bütün alt nesneler için gerekli hafıza tahsis edilmelidir.

– (2) verilen nesnenin alt nesnelerinin içeriği kopya nesnelere verilmelidir.

11/8/2007 Nesneye Yonelik Programlama 8.26

Copy Constructor

• sınıf için kopya yapıcı tanımlandığında, kopya yapıcı otomatik olarak aşağıdaki durumlarda çağrılır

– Bir nesne fonksiyona değerle iletildiğinde – Bir fonksiyondan bir nesne döndürüldüğünde – Var olan bir nesnenin kopyası olarak yeni bir

nesneye başlangıç ataması yapıldığında.

Atama Operatörünün Aşırı Yüklenmesi

• Sınıf deklarasyonunda

const <class> &operator= (const <class> &);

• Diğer ikili operatörlerin aşırı yüklenmesinde olduğu gibi, derleyiciye şu kod örneğini

object1 = object2;

aşağıdaki fonksiyon çağrılmasıyla yer değiştirir:

object1.operator= (object2);

• Atama operatörü fonksiyon tanımında

– Kendi kendisine atama yapmaya izin verilmemelidir.

– Zincirleme atamalara izin vermek için nesne bir işaretçi geri döndür ( return *this)

(örnek: object1 = object2 = object3; )

built-in tipler arasında dönüştürme

• C++ derleyicileri operatörler farkliı tipe sahip argümanlara uygulandığında güvenli tipe çevrimleri için otomatik olarak kod yerleştirir (promotion veya implicit conversion)

Örnek: int + double double sonuç üretir.

• Bazen programcı explicit (açık) tip dönüştürmeye ihtiyac duyar

Örnek: avg = static_cast <float> (sum) / num;

Yazım: static_cast < <typeName> > ( <argument>)

(8)

11/8/2007 Nesneye Yonelik Programlama 8.29

Kullanıcı tanımlı tipler arasında dönüştürmeye

• Bazen kullanıcı tanımlı tipler arasında dönüştürmeye ihtiyaç duyabiliriz.

• Bunun için programcı dönüşüm fonksiyonları tanımlamalıdır:

• Dönüştürme Yapıcıları - Conversion constructors:

– Tek argüman alan ve argüman tipini (built-in type veya user-defined type) nesne tipine çeviren yapıcı.

• Dönüştürme operatöerleri - Conversion ( cast ) operators:

– Non-static üye fonksiyonları kullanarak bir sınıfa ait nesneyi

• başka bir sınıfın nesnesine dönüştürür.

• hali hazırda var olan tiplerdeki nesneye dönüştürür.

11/8/2007 Nesneye Yonelik Programlama 8.30

Dönüştürme Operatör Fonksiyonları

• Dönüştürme operatör deklarasyonu yazımı:

<old_class>::operator<new_class> const;

• Anlamı:

Giriş parametresi <old_class> tipinden

<new_class> sınıfının bir nesnesine dönüştürür – Geri dönüş tipi gerekmez

– Dönüştürme operator şöyle çağrılır:

(newClass ) objectName ;

Aşırı yüklenmiş dönüştürme operatör fonksiyonları overloaded cast operator functions

• İki veya daha fazla dönüştürme operatörü aşırı yüklenmek suretiyle sınıfın nesnesi iki veya daha fazla kullanıcı tanımlı sınıfların nesnelerine dönüştürülür

class A { public:

operator int( ) const;

operator double ( ) const;

operator B ( ) const;

private:

};

Dönüştürme operatörlerini kullanarak kapalı dönüştürme

• Bir dizi dönüştürme fonksiyonu tanımlandığı zaman derleyici bunları kullanarak kapalı tip dönüştürme (implicit type conversion) yapar.

• Örnek: Kullanıcı tarafından bir dönüştürme operatörü tanımlandığını ve bunun A sınıfının nesnelerini char * ya çevirdiğini varsayalım:

• Derleyici operatör char * otomatik olarak çağırmak suretiyle aşağıdaki kodun doğru sonuç üretmesini sağlayacak

cout << objectName; // objectName A sınıfının nesnesi

(9)

11/8/2007 Nesneye Yonelik Programlama 8.33

Overloading ++ and --

• Önek (prefix) operatörleri (önceden artırma ve önceden azaltma) diğer tekli önek (prefix unary) operatörler gibi düşünülerek aşırı yüklenebilirler.

• Sonek (postfix) operatörler (sonradan artırma ve sonradan azaltma) operatörlere 0 değerli bir sahte giriş parametresi verilmek suretiyle önekli

versiyonlarından ayırt edilirler.

11/8/2007 Nesneye Yonelik Programlama 8.34

Önceden artırma operatörünü aşırı yükleme

• Method 1: üye fonksiyon kullanarak – s nin A sınıfınin nesnesi olduğunu varsayalım – Derleyici ++s yi gördüğünde

– s.operator++( ) yi üretir.

– Dolayısıyla A sınıfı, A &operator++( ) üye fonksiyonuna sahip olmalıdır.

– Fonksiyon tanımlaması A &A::operator++( )

• Method 2: üye olmayan friend fonksiyonu kullanarak – friend A &operator++(A &) // decleration – A &operator++ (A &) // definition

Sonradan artırma operatörünü aşırı yükleme

• Method 1: üye fonksiyonu kullanarak – s nin A sınıfının nesnesi olduğunu varsayalım – Derleyici s++ yı gördüğünde

– s.operator++(0) yi üretir.

– Dolayısıyla A sınıfı, A &operator++(int) üye fonksiyonuna sahip olmalıdır.

– Fonksiyon tanımlama A &A::operator++(int)

• Method 2: üye olmayan friend fonksiyonu kullanarak – friend A &operator++ (A &, int) // decleration – A &operator++ (A &, int) // definition

#include <iostream.h>

#include <stdlib.h>

struct CELL{

int element;

struct CELL *next;

};

class List{

public:

List( );

List(const List &);

~List( );

void Add_element(int);

void Remove_element(int);

void print( );

const List& operator=(const List &);

const List& operator++();

const List operator++(int);

void sort( );

private:

struct CELL *list_header;

struct CELL* create_element(int);

struct CELL* insert_sorted_list(struct CELL*,struct CELL*);

(10)

11/8/2007 Nesneye Yonelik Programlama 8.37 struct CELL* List::create_element(int i) {

struct CELL *ptr;

ptr = (struct CELL *) malloc(sizeof(struct CELL));

ptr->element = i;

return ptr;

}

11/8/2007 Nesneye Yonelik Programlama 8.38

List::List( ) {

cout<<"birinci List constructor cagrildi\n";

list_header = 0;

}

List::List(const List &list){ struct CELL *temp1, *temp2;

cout<<"ikinci List constructor cagrildi\n";

list_header = 0;

if(list.list_header == 0) return;

temp2=list.list_header;

temp1 = list_header =

create_element(temp2->element);

temp2 = temp2->next;

while(temp2) {

temp1->next = create_element(temp2-

>element);

temp2 = temp2->next;

temp1 = temp1->next;

}

temp1->next = 0;

}

List::~List( ) { struct CELL *temp;

cout << “List destructor cagrildi\n";

temp= list_header;

while(temp) {

list_header = list_header->next;

delete temp;

temp=list_header;

} }

const List& List::operator=(const List & input_list){ struct CELL *header1 = list_header;

struct CELL *header2 = input_list.list_header, *temp = 0;

if(header2==0) list_header = 0;

while (header1 && header2) {

temp = header1; header1->element = header2->element;

header1 = header1->next; header2 = header2->next;

} // while if(header2 == 0) {

if (temp) temp->next = 0;

temp = header1;

while (temp) {

header1 = header1->next;

delete temp; temp = header1;

} // while } // if (header == 0) else {

if(header2 && !list_header) {

list_header = temp = create_element(header2->element);

header2=header2->next;

}

while(header2) {

temp->next = create_element(header2->element);

temp = temp->next; header2 = header2->next;

} // while

if(temp) temp->next = 0;

} // else return *this;

(11)

11/8/2007 Nesneye Yonelik Programlama 8.41 const List& List::operator ++() {

struct CELL *temp = list_header;

while(temp) { temp->element++;

temp = temp->next;

}

return *this;

}

const List List::operator ++(int) { struct CELL *temp_header = list_header;

List temp = *this;

while(temp_header) { temp_header->element++;

temp_header = temp_header->next;

}

return temp;

}

11/8/2007 Nesneye Yonelik Programlama 8.42

void List::Add_element(int i) {

struct CELL *new_element_ptr = create_element(i);

new_element_ptr->next = list_header;

list_header = new_element_ptr;

}

void List::Remove_element(int i) { struct CELL *temp1,*temp2;

temp1=temp2=list_header;

while(temp2) {

if(temp2->element == i) {

if(temp1==temp2) list_header = temp2->next;

else temp1->next=temp2->next;

free(temp2);

break;

}

temp1=temp2;

temp2=temp2->next;

} }

void List::print( ) {

struct CELL *temp_ptr = list_header;

cout<<endl;

while(temp_ptr) {

cout << temp_ptr->element <<“ “;

temp_ptr=temp_ptr->next;

}

cout <<endl;

}

struct CELL* List::insert_sorted_list(struct CELL* header, struct CELL* cell) { if(!header) {

cell->next = 0;

return cell;

}

else if(cell->element <= header->element) { cell->next = header;

return cell;

} else {

header->next = insert_sorted_list(header->next,cell);

return header;

} }

void List::sort( ) {

struct CELL *temp1,*temp2;

temp1 = list_header;

list_header = 0;

while (temp1) { temp2=temp1->next;

list_header = insert_sorted_list(list_header,temp1);

temp1 = temp2;

(12)

11/8/2007 Nesneye Yonelik Programlama 8.45 class Stack{

public:

Stack( ); // default constructor Stack(Stack &); // copy constructor

~Stack( ); // destructor void push(int);

bool pop(int &);

void print( );

operator List( ) const; // overloading cost operator

operator List*( ) const; // overloading cost operator

private:

struct CELL *stack_ptr;

};

11/8/2007 Nesneye Yonelik Programlama 8.46

Stack::Stack( ) {

cout << "birinci Stack constructor cagrildi\n";

stack_ptr = 0;

}

Stack::Stack(Stack & stack) { CELL *temp = stack.stack_ptr;

CELL *cell;

cout << “ikinci Stack constructor cagrildi\n";

stack_ptr = 0;

if (!temp) return;

stack_ptr = cell =

(struct CELL *) malloc(sizeof(struct CELL));

cell->element = temp->element;

temp = temp->next;

while(temp) { cell->next =

(struct CELL *) malloc(sizeof(struct CELL));

cell->next->element = temp->element;

cell = cell->next;

temp = temp->next;

}

cell->next = 0;

}

Stack::~Stack( ) { CELL *temp;

cout <<"Stack destructor cagrildi\n";

while(stack_ptr) {

temp = stack_ptr->next;

free(stack_ptr);

stack_ptr = temp;

} }

void Stack::push(int element) {

CELL *cell = (struct CELL *) malloc(sizeof(struct CELL));

cell->element = element;

cell->next = stack_ptr;

stack_ptr = cell;

}

bool Stack::pop(int &element) { if(!stack_ptr) return false;

else {

CELL *cell = stack_ptr->next;

element = stack_ptr->element;

free(stack_ptr);

stack_ptr = cell;

return true;

} }

void Stack::print( ) { CELL *cell = stack_ptr;

cout << endl;

while(cell) {

cout << cell->element <<" ";

cell = cell->next;

}

cout << endl;

}

(13)

11/8/2007 Nesneye Yonelik Programlama 8.49 Stack::operator List( ) const {

List list;

CELL *cell = stack_ptr;

while(cell) {

list.Add_element(cell->element);

cell = cell->next;

}

return list;

}

Stack::operator List*( ) const { List *list = new List;

CELL *cell = stack_ptr;

while(cell) {

list->Add_element(cell->element);

cell = cell->next;

}

return list;

}

11/8/2007 Nesneye Yonelik Programlama 8.50

int main( ) {

class List list1; // 1

list1.Add_element(10); // 2

list1.Add_element(20); // 3 list1.Add_element(40); list1.print(); // 4 class List list2; // 5

list2 = list1++; // 6

list1.print(); // 7

list2.print(); // 8

class Stack stack1; // 9 stack1.push(3000); stack1.push(5000); // 10 stack1.push(1000); stack1.push(4000); // 11

stack1.print( ); // 12

class Stack stack2 = stack1; // 13

int element; // 14

if (stack2.pop(element)) // 15 cout << element <<endl; // 16

stack2.print( ); // 17

list1 = (List) stack2; // 18 cout <<"---\n"; // 19

list1.print( ); // 20

class List *list_ptr; // 21 list_ptr = (List*)stack1; // 22 list_ptr->print( ); // 23

delete list_ptr; // 24

return 0; // 25

}

Referanslar

Benzer Belgeler

Yeni Zelanda’da yüksek volkanik etkinliğe sahip bir bölgedeki bitkiler üzerinde yapılan incelemeler sonucunda aşırı sıcak topraklarda yaşayabilen bitkilere rastlandı..

Oysa Vedat Kosal, Cemal Reşid'in o tarihlerdeki çok yönlülüğünü şöyle eleş­ tiriyor: “Müzisyen komple dediği şeyin devri çoktan geçmişti.. O, hem orkestra

Geçtiğimiz aylarda bir polisi tokatladığı gerekçesiyle günlerce basını meşgul eden Zsa Zsa Gabor şimdi Amerikan Ormancılık Hizmetleri adında çevreci bir

Geleneksel toplumlar doğal kaynakların aşırı sömürülmesini önlemek için çeşitli önlemler almışlardır... Ekonomik açıdan kamusal bir kaynak erişime açık bir

- Karbonik asidin oluşumunun azalması proksimal tubül hücrelerinde daha az H iyonunun bulunmasına yol açar.. - Normalde, H iyonları tubül hücrelerinde

- Farklı sınıflardan diüretikleri kombine etmek, additif veya potansiyel olarak sinerjik etkilere yol açabilir.... Aldosteronun yarışmalı

Ve ben şimdi daha da keskin bir yoksulluk içindeyim Güneşin içinden sana dokuyorum bu yakıcı şiiri Yüzünü bilmem kaç kez sarıp sarmalayan şu kundağı Kalbimin ayin

Stria distensa, obez grupta diğer iki gruptan istatistiksel olarak anlamlı derecede fazla iken aşırı kilolu grup ile kontrol grubu arasında istatistiksel olarak anlamlı