İşlemin Aşırı Yüklenmesi

Kodun okunmasını ve yazılmasını kolaylaştırması için aşırı yüklemeye izin verilir. Aşırı yükleme operatörü operator anahtar sözcüğü ile yazılır. Şu operatörler aşırı yüklenebilir:

  • ikili +,-,/,*,%,<<,>>,==,!=,<,>,<=,>=,=,+=,-=,/=,*=,%=,&=,|=,^=,<<=,>>=,&&,||,&,|,^
  • tekli +,-,++,--,!,~
  • atama operatörü =
  • indisleme operatörü []

 

İşlemin aşırı yüklenmesi, karmaşık nesneler - yapılar ve sınıflar için (basit ifadeler şeklinde yazılmış) işlem notasyonunun kullanılmasını sağlar. Kodu aşırı yüklenmiş operatörler kullanarak yazmak kaynak kodunun görünümünü basitleştirir, çünkü daha karmaşık uygulamalar gizlenecektir.

Örneğin, gerçel ve imajiner kısımlardan meydana gelen karmaşık sayıları ele alalım. Bu sayılar matematikte sıklıkla kullanılırlar. MQL5 dili içerisinde karmaşık sayıları temsil eden bir veri tipi yer almaz ama bir yapı veya sınıf şeklinde yeni bir tip oluşturmak mümkündür. Karmaşık yapının bildirimi ve dört aritmetik işlem gerçekleştiren dört ayrı yöntemin tanımı:

//+------------------------------------------------------------------+
//| Karmaşık sayılı işlemler için bir yapı                           |
//+------------------------------------------------------------------+
struct complex
  {
   double            re; // Gerçel kısım
   double            im; // İmajiner kısım
   //--- Yapıcılar
                     complex():re(0.0),im(0.0) {  }
                     complex(const double r):re(r),im(0.0) {  }
                     complex(const double r,const double i):re(r),im(i) {  }
                     complex(const complex &o):re(o.re),im(o.im) { }
   //--- Aritmetik işlemler
   complex           Add(const complex &l,const complex &r) const;  // Toplama
   complex           Sub(const complex &l,const complex &r) const;  // Çıkarma
   complex           Mul(const complex &l,const complex &r) const;  // Çarpma
   complex           Div(const complex &l,const complex &r) const;  // Bölme
  };

Şimdi, kodumuzda karmaşık sayıları temsil eden değişkenleri bildirilebilir, ardından bunlarla çalışabiliriz.

Örneğin:

void OnStart()
  {
//--- Karmaşık tipli değişkenleri bildir ve başlat
   complex a(2,4),b(-4,-2);
   PrintFormat("a=%.2f+i*%.2f,   b=%.2f+i*%.2f",a.re,a.im,b.re,b.im);
//--- İki sayıyı topla
   complex z;
   z=a.Add(a,b);
   PrintFormat("a+b=%.2f+i*%.2f",z.re,z.im);
//--- İki sayıyı çarp
   z=a.Mul(a,b);
   PrintFormat("a*b=%.2f+i*%.2f",z.re,z.im);
//--- İki sayıyı böl
   z=a.Div(a,b);
   PrintFormat("a/b=%.2f+i*%.2f",z.re,z.im);
//---
  }

Ama, alışıldık aritmetik işlemleri karmaşık sayılarla yapmak için; "+", "-", "*" ve "/" şeklindeki alışıldık operatörleri kullanmak daha uygun olacaktır.

'operator' anahtar kelimesi, dönüşümü gerçekleştiren bir üye fonksiyonunu tanımlamak için kullanılır. Sınıf nesnesi değişkenleri için yapılan tekli ve ikili işlemler, statik olmayan üye fonksiyonları gibi aşırı yüklenmiş olabilirler. Bunlar sınıf nesnesi üzerinde gizlice hareket ederler.

Bir sınıf nesnesi veya bu sınıfın bir nesnesinin işaretçisi şeklinde bir veya iki argümanı olan düzenli fonksiyonlar gibi, bir çok ikili işlem de aşırı yüklenebilir. Bizim oluşturduğumuz tip (complex) için, bildirim içindeki aşırı yükleme şöyle gözükecektir:

   //--- Operatörler
   complex operator+(const complex &r) const { return(Add(this,r)); }
   complex operator-(const complex &r) const { return(Sub(this,r)); }
   complex operator*(const complex &r) const { return(Mul(this,r)); }
   complex operator/(const complex &r) const { return(Div(this,r)); }

Betik örneğinin bütünü:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- complex tipindeki değişkenleri bildir ve başlat
   complex a(2,4),b(-4,-2);
   PrintFormat("a=%.2f+i*%.2f,   b=%.2f+i*%.2f",a.re,a.im,b.re,b.im);
   //a.re=5;
   //a.im=1;
   //b.re=-1;
   //b.im=-5;
//--- İki sayıyı topla
   complex z=a+b;
   PrintFormat("a+b=%.2f+i*%.2f",z.re,z.im);
//--- İki sayıyı çarp
 
   z=a*b;
   PrintFormat("a*b=%.2f+i*%.2f",z.re,z.im);
//--- İki sayıyı böl
   z=a/b;
   PrintFormat("a/b=%.2f+i*%.2f",z.re,z.im);
//---
  }
//+------------------------------------------------------------------+
//| Karmaşık sayılı işlemler için bir yapı                           |
//+------------------------------------------------------------------+
struct complex
  {
   double            re; // Gerçel kısım
   double            im; // İmajiner kısım
   //--- Yapıcılar
                     complex():re(0.0),im(0.0) {  }
                     complex(const double r):re(r),im(0.0) {  }
                     complex(const double r,const double i):re(r),im(i) {  }
                     complex(const complex &o):re(o.re),im(o.im) { }
   //--- Aritmetik işlemler
   complex           Add(const complex &l,const complex &r) const;  // Toplama
   complex           Sub(const complex &l,const complex &r) const;  // Çıkarma
   complex           Mul(const complex &l,const complex &r) const;  // Çarpma
   complex           Div(const complex &l,const complex &r) const;  // Bölme
   //--- İkili operatörler
   complex operator+(const complex &r) const { return(Add(this,r)); }
   complex operator-(const complex &r) const { return(Sub(this,r)); }
   complex operator*(const complex &r) const { return(Mul(this,r)); }
   complex operator/(const complex &r) const { return(Div(this,r)); }
  };
//+------------------------------------------------------------------+
//| Toplama                                                          |
//+------------------------------------------------------------------+
complex complex::Add(const complex &l,const complex &r) const
  {
   complex res;
//---
   res.re=l.re+r.re;
   res.im=l.im+r.im;
//--- Sonuç
   return res;
  }
//+------------------------------------------------------------------+
//| Çıkarma                                                          |
//+------------------------------------------------------------------+
complex complex::Sub(const complex &l,const complex &r) const
  {
   complex res;
//---
   res.re=l.re-r.re;
   res.im=l.im-r.im;
//--- Sonuç
   return res;
  }
//+------------------------------------------------------------------+
//| Çarpma                                                           |
//+------------------------------------------------------------------+
complex complex::Mul(const complex &l,const complex &r) const
  {
   complex res;
//---
   res.re=l.re*r.re-l.im*r.im;
   res.im=l.re*r.im+l.im*r.re;
//--- Sonuç
   return res;
  }
//+------------------------------------------------------------------+
//| Bölme                                                            |
//+------------------------------------------------------------------+
complex complex::Div(const complex &l,const complex &r) const
  {
//--- Boş karmaşık sayılar
   complex res(EMPTY_VALUE,EMPTY_VALUE);
//--- Sıfır için kontrol et
   if(r.re==0 && r.im==0)
     {
      Print(__FUNCTION__+": sayı sıfıra eşittir");
      return(res);
     }
//--- Yardımcı değişkenler
   double e;
   double f;
//--- Hesaplama Türevinin seçimi
   if(MathAbs(r.im)<MathAbs(r.re))
     {
      e = r.im/r.re;
      f = r.re+r.im*e;
      res.re=(l.re+l.im*e)/f;
      res.im=(l.im-l.re*e)/f;
     }
   else
     {
      e = r.re/r.im;
      f = r.im+r.re*e;
      res.re=(l.im+l.re*e)/f;
      res.im=(-l.re+l.im*e)/f;
     }
//--- Sonuç
   return res;
  }

 

Bir tekil sınıf nesnesini veya bunun işaretçisini argümanı olarak kabul eden normal fonksiyonlar gibi, sınıflar için gerçekleştirilen bir çok tekli işlem de aşırı yüklenmiş olabilir. "-" ve "!" tekli işlemlerinin aşırı yüklenmesini ekle.

//+------------------------------------------------------------------+
//| Karmaşık sayılı işlemler için bir yapı                           |
//+------------------------------------------------------------------+
struct complex
  {
   double            re;       // Gerçel kısım
   double            im;       // İmajiner kısım
... 
   //--- Tekli operatörler
   complex operator-()  const// Tekli eksi
   bool    operator!()  const// Red
  };
... 
//+------------------------------------------------------------------+
//| "Tekil eksi" operatörünün aşırı yüklenmesi                       |
//+------------------------------------------------------------------+
complex complex::operator-() const
  {
   complex res;
//---
   res.re=-re;
   res.im=-im;
//--- Sonuç
   return res;
  }
//+------------------------------------------------------------------+
//| "Mantıksal red" operatörünün aşırı yüklenmesi                    |
//+------------------------------------------------------------------+
bool complex::operator!() const
  {
//--- Karmaşık sayının gerçel ve imajiner kısımları sıfır mı?
   return (re!=0 && im!=0);
  }

 

Artık karmaşık sayıyı sıfır değeri için kontrol edebilir ve red değeri alabiliriz:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- complex tipindeki değişkenleri bildir ve başlat
   complex a(2,4),b(-4,-2);
   PrintFormat("a=%.2f+i*%.2f,   b=%.2f+i*%.2f",a.re,a.im,b.re,b.im);
//--- İki sayıyı böl
   complex z=a/b;
   PrintFormat("a/b=%.2f+i*%.2f",z.re,z.im);
//--- Varsayılan olarak bir karmaşık sayı sıfıra eşittir (Yani re==0 ve im==0)
   complex zero;
   Print("!zero=",!zero);
//--- Negatif değer ata
   zero=-z;
   PrintFormat("z=%.2f+i*%.2f,  zero=%.2f+i*%.2f",z.re,z.im, zero.re,zero.im);
   PrintFormat("-zero=%.2f+i*%.2f",-zero.re,-zero.im);
//--- Bir kez daha sıfır için kontrol et  
   Print("!zero=",!zero);
//---
  }

Basit tipli yapıların birinden diğerine doğrudan kopyalanabildiği düşünüldüğünde, "=" atama operatörüne aşırı yükleme yapmamızın gerekli olmadığı not edilmelidir. Artık, karmaşık sayıları alışıldık tarzda kullanan hesaplamalar için bir kod yazabiliriz.

İndisleme operatörünün aşırı yüklenmesi, nesneye iliştirilmiş dizilerin değerlerinin basitçe alınmasını sağlar. Ayrıca kodun okunabilirliğini artırmaya da yardımcı olur. Örneğin, dizgi içinde belirli konumdaki bir sembole erişim sağlamamız gerekebilir. Dizgi, MQL5 içinde ayrı bir tiptir (string), sembollerden oluşan bir dizi değildir. Ama aşırı yüklenmiş bir indisleme operatörünün yardımıyla, CString sınıfı içerisinde basit ve saydam bir çalışma sağlanabilir:

//+---------------------------------------------------------------------------------+
//| Bir dizgideki sembollere, sembol dizisiymiş gibi erişim sağlamak için bir sınıf |
//+---------------------------------------------------------------------------------+
class CString
  {
   string            m_string;
  
public:
                     CString(string str=NULL):m_string(str) { }
   ushort operator[] (int x) { return(StringGetCharacter(m_string,x)); }
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()  
  {
//--- Bir dizgiden sembolleri almak için bir dizi
   int     x[]={ 19,4,18,19,27,14,15,4,17,0,19,14,17,27,26,28,27,5,14,
                 17,27,2,11,0,18,18,27,29,30,19,17,8,13,6 };
   CString str("abcdefghijklmnopqrstuvwxyz[ ]CS");
   string  res;
//--- str değişkeni içindeki sembolleri kullanarak bir cümle oluştur
   for(int i=0,n=ArraySize(x);i<n;i++)
     {
      res+=ShortToString(str[x[i]]);
     }
//--- Sonucu göster
   Print(res);
  }

 

İndisleme operatörünün aşırı yüklenmesine bir örnek de matris işlemleridir. Matris iki boyutlu bir dinamik diziyi ifade eder ama dizi büyüklüğü peşin olarak tanımlanmaz. Bu yüzden, array[][] şeklinde bir diziyi, ikinci boyutun büyüklüğünü tanımlamadan ve diziyi bir parametre olarak geçirmeden bildiremezsiniz. Bu soruna getirilebilecek özel bir çözüm CMatrix sınıfıdır. Bu, CRow sınıf nesnelerinin bir dizisini içerir.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Matrislerin toplanması ve çarpımı işlemleri
   CMatrix A(3),B(3),C();
//--- Satılar için bir dizi hazırla
   double a1[3]={1,2,3}, a2[3]={2,3,1}, a3[3]={3,1,2};
   double b1[3]={3,2,1}, b2[3]={1,3,2}, b3[3]={2,1,3};
//--- Matrisleri doldur
   A[0]=a1; A[1]=a2; A[2]=a3;
   B[0]=b1; B[1]=b2; B[2]=b3;
//--- Matrisleri Uzmanlar günlüğüne çıktıla
   Print("---- Matris A elemanları");
   Print(A.String());
   Print("---- Matris B elemanları");
   Print(B.String());
 
//--- Matrislerin toplamı
   Print("---- A ve B matrislerinin toplamı");
   C=A+B;
//--- Biçimlendirilmiş dizgi ifadesini çıktıla
   Print(C.String());
 
//--- Matrislerin çarpımı
   Print("---- A ve B matrislerinin çarpımı");
   C=A*B;
   Print(C.String());
 
//--- Şimdi değerleri matrix[i][j] dinamik dizileri şeklinde nasıl elde edeceğimizi gösterelim
   Print("C matrisi değerlerini elementsel olarak çıktıla");
//--- Matris satırlarını - CRow nesneleri - bir döngü içinde incele
   for(int i=0;i<3;i++)
     {
      string com="| ";
      //--- Değer için matris satırlarından
      for(int j=0;j<3;j++)
        {
         //--- Matris elemanlarını satır ve sütun numarası kullanarak al
         double element=C[i][j];// [i] - m_rows[] dizisi içinde CRow'a erişim,
                                // [j] - CRow içinde yapılan indislemenin aşırı yükleme operatörü
         com=com+StringFormat("a(%d,%d)=%G ; ",i,j,element);
        }
      com+="|";
      //--- Satır değerlerinin çıktısını al
      Print(com);
     }
  }
//+------------------------------------------------------------------+
//| "Row" sınıfı                                                     |
//+------------------------------------------------------------------+
class CRow
  {
private:
   double            m_array[];
public:
   //--- Yapıcılar ve bir yıkıcı
                     CRow(void)          { ArrayResize(m_array,0);    }
                     CRow(const CRow &r) { this=r;                    }
                     CRow(const double &array[]);
                    ~CRow(void){};
   //--- Satırdaki elemanların sayısı
   int               Size(voidconst    { return(ArraySize(m_array));}
   //--- Değerleriyle bir dizgiye dönüş yapar
   string            String(voidconst;
   //--- İndisleme operatörü
   double            operator[](int i) const  { return(m_array[i]);   }
   //--- Atama operatörleri
   void              operator=(const double  &array[]); // Bir dizi
   void              operator=(const CRow & r);         // Başka bir CRow nesnesi
   double            operator*(const CRow &o);          // Çarpım için CRow nesnesi
  };
//+------------------------------------------------------------------+
//| Tek satırlı bir dizinin başlatılması için yapıcı                 |
//+------------------------------------------------------------------+
void  CRow::CRow(const double &array[])
  {
   int size=ArraySize(array);
//--- Eğer dizi boş değilse
   if(size>0)
     {
      ArrayResize(m_array,size);
      //--- Değerler ile doldur
      for(int i=0;i<size;i++)
         m_array[i]=array[i];
     }
//---
  }
//+------------------------------------------------------------------+
//| Dizi için atama işlemi                                           |
//+------------------------------------------------------------------+
void CRow::operator=(const double &array[])
  {
   int size=ArraySize(array);
   if(size==0) return;
//--- Diziyi değerlerle doldur
   ArrayResize(m_array,size);
   for(int i=0;i<size;i++) m_array[i]=array[i];
//--- 
  }
//+------------------------------------------------------------------+
//| CRow için atama operatörü                                        |
//+------------------------------------------------------------------+
void CRow::operator=(const CRow  &r)
  {
   int size=r.Size();
   if(size==0) return;
//--- Diziyi değerlerle doldur
   ArrayResize(m_array,size);
   for(int i=0;i<size;i++) m_array[i]=r[i];
//--- 
  }
//+------------------------------------------------------------------+
//| Başka bir satırla çarpma operatörü                               |
//+------------------------------------------------------------------+
double CRow::operator*(const CRow &o)
  {
   double res=0;
//--- Doğrulamalar
   int size=Size();
   if(size!=o.Size() || size==0)
     {
      Print(__FUNCSIG__,": İki matrisin çarpımı başarısız oldu, büyüklükler farklı");
      return(res);
     }
//--- Dizileri elementsel olarak çarp ve çarpımları ekle
   for(int i=0;i<size;i++)
      res+=m_array[i]*o[i];
//--- Sonuç
   return(res);
  }
//+------------------------------------------------------------------+
//| Biçimlendirilmiş bir dizgi ifadesine dönüş yapar                 |
//+------------------------------------------------------------------+
string CRow::String(voidconst
  {
   string out="";
//--- Dizi büyüklüğü sıfırdan büyükse
   int size=ArraySize(m_array);
//--- Dizinin sadece sıfır olmayan elemanlarıyla çalışacağız
   if(size>0)
     {
      out="{";
      for(int i=0;i<size;i++)
        {
         //--- Değerleri dizgiye topla
         out+=StringFormat(" %G;",m_array[i]);
        }
      out+=" }";
     }
//--- Sonuç
   return(out);
  }
//+------------------------------------------------------------------+
//| "Matrix" sınıfı                                                  |
//+------------------------------------------------------------------+
class CMatrix
  {
private:
   CRow              m_rows[];
 
public:
   //--- Yapıcılar ve bir yıkıcı
                     CMatrix(void);
                     CMatrix(int rows)  { ArrayResize(m_rows,rows);             }
                    ~CMatrix(void){};
   //--- Matris büyüklüklerini al
   int               Rows()       const { return(ArraySize(m_rows));            }
   int               Cols()       const { return(Rows()>0? m_rows[0].Size():0); }
   //--- Sütun değerini CRow satırı şeklinde dönüş yapar
   CRow              GetColumnAsRow(const int col_index) const;
   //--- Matris değerli bir dizgiye dönüş yapar
   string            String(voidconst;
   //--- İndisleme operatörü numarası ile bir dizgiye dönüş yapar
   CRow *operator[](int i) const        { return(GetPointer(m_rows[i]));        }
   //--- Toplama operatörü
   CMatrix           operator+(const CMatrix &m);
   //--- Çarpma operatörü
   CMatrix           operator*(const CMatrix &m);
   //--- Atama operatörü
   CMatrix          *operator=(const CMatrix &m);
  };
//+--------------------------------------------------------------------+
//| Ön tanılı bir yapıcı, sıfır büyüklüğünde bir satır dizisi oluştur  |
//+--------------------------------------------------------------------+
CMatrix::CMatrix(void)
  {
//--- Matristeki sıfır sayılı satırlar
   ArrayResize(m_rows,0);
//---  
  }
//+------------------------------------------------------------------+
//| CRow şeklindeki sütun değerine dönüş yapar                       |
//+------------------------------------------------------------------+
CRow  CMatrix::GetColumnAsRow(const int col_index) const
  {
//--- Sütundan değerleri almak için bir değişken
   CRow row();
//--- Matristeki satırların sayısı
   int rows=Rows();
//--- satır sayısı sıfırdan büyükse, işlemi başlat
   if(rows>0)
     {
      //--- col_index indisli sütun değerlerinin alımı için bir dizi
      double array[];
      ArrayResize(array,rows);
      //--- Dizinin doldurulması
      for(int i=0;i<rows;i++)
        {
         //--- i satırı için sütun sayısını kontrol et - dizi sınırlarını aşabilir
         if(col_index>=this[i].Size())
           {
            Print(__FUNCSIG__,": Hata! Sütun numarası ",col_index,"> satır büyüklüğü ",i);
            break// satır, başlatılmamış nesne olacak
           }
         array[i]=this[i][col_index];
        }
      //--- Dizi değerlerine göre bir CRow satırı oluştur
      row=array;
     }
//--- Sonuç
   return(row);
  }
//+------------------------------------------------------------------+
//| İki matrisin toplanması                                          |
//+------------------------------------------------------------------+
CMatrix CMatrix::operator+(const CMatrix &m)
  {
//--- Geçirilmiş matristeki satır ve sütunların sayısı
   int cols=m.Cols();
   int rows=m.Rows();
//--- Toplama sonuçlarının alınacağı matris
   CMatrix res(rows);
//--- Matrislerin büyüklükleri eşleşmeli
   if(cols!=Cols() || rows!=Rows())
     {
      //--- Toplama imkansız
      Print(__FUNCSIG__,": Matrislerin toplanması başarısız, büyüklükleri uyuşmuyor");
      return(res);
     }
//--- Yardımcı dizi
   double arr[];
   ArrayResize(arr,cols);
//--- Toplanacak satırları incele
   for(int i=0;i<rows;i++)
     {
      //--- Matris dizgilerinin toplamlarını diziye yaz
      for(int k=0;k<cols;k++)
        {
         arr[k]=this[i][k]+m[i][k];
        }
      //--- Diziyi matris satırına yerleştir
      res[i]=arr;
     }
//--- Matrislerin toplama sonucuna dönüş yap
   return(res);
  }
//+------------------------------------------------------------------+
//| İki matrisin çarpımı                                             |
//+------------------------------------------------------------------+
CMatrix CMatrix::operator*(const CMatrix &m)
  {
//--- İlk matristeki sütunların sayısı, matrise geçirilmiş satırların sayısı
   int cols1=Cols();
   int rows2=m.Rows();
   int rows1=Rows();
   int cols2=m.Cols();
//--- Toplama sonuçlarını alacak matris
   CMatrix res(rows1);
//--- Matrisler koordine edilmeli
   if(cols1!=rows2)
     {
      //--- Çarpma işlemi imkansız
      Print(__FUNCSIG__,": Matrislerin çarpımı başarısız oldu, biçim uyumsuz "
            "- ilk matristeki sütun sayısı ikinci matrisin satır sayısına eşit olmalı");
      return(res);
     }
//--- Yardımcı dizi
   double arr[];
   ArrayResize(arr,cols1);
//--- Çarpım matrisinin satırlarını doldur
   for(int i=0;i<rows1;i++)// Satırları incele
     {
      //--- Alınan diziyi sıfırla
      ArrayInitialize(arr,0);
      //--- Satırdaki elemanları incele
      for(int k=0;k<cols1;k++)
        {
         //--- Matrisin k sütununun değerlerini CRow şeklinde al 
         CRow column=m.GetColumnAsRow(k);
         //--- iki satırı skaler olarak çarp ve vektörlerin çarpım sonucunu i-inci elemanda yaz
         arr[k]=this[i]*column;
        }
      //--- Matrisin i-inci satırına arr[] dizisini yerleştir
      res[i]=arr;
     }
//--- Matrislerin çarpımına dönüş yap
   return(res);
  }
//+------------------------------------------------------------------+
//| Atama işlemi                                                     |
//+------------------------------------------------------------------+
CMatrix *CMatrix::operator=(const CMatrix &m)
  {
//--- Satır sayısını bul ve ayarla
   int rows=m.Rows();
   ArrayResize(m_rows,rows);
//--- Satırlarımızı, geçirilmiş matrisin değerleri ile doldur
   for(int i=0;i<rows;i++) this[i]=m[i];
//---
   return(GetPointer(this));
  }
//+------------------------------------------------------------------+
//| Matrisin dizgi şeklinde gösterimi                                |
//+------------------------------------------------------------------+
string CMatrix::String(voidconst
  {
   string out="";
   int rows=Rows();
//--- Dizgileri tek tek şekillendir
   for(int i=0;i<rows;i++)
     {
      out=out+this[i].String()+"\r\n";
     }
//--- Sonuç
   return(out);
  }

Ayrıca Bakınız

Aşırı Yükleme, Aritmetik İşlemler, Fonksiyonun Aşırı Yüklenmesi, Öncelik Kuralları