Едноаргументният конструктор
(The One-Argument Constructor)
.
(съдържание)
Едноаргументният
конструктор играе специална роля в обектно-ориентираното програмиране.
Той може да се използва за преобразуване на обект от един клас в обект
от друг, затова другото име за този тип конструктори е преобразуваща
функция (conversion function).
.
1. Едноаргументен
конструктор.
В
предишната
лекция 32
в т. 3 бяха написани два (!) едноаргументни конструктора в дадената примерна
програма. Това бяха следните два конструктора (от общо четири):
richman(int m) : name("Angel"), money(m)
{ }
richman(string n) : name(n), money(-1)
{ }
Първият при инициализиране с някаква сума пари предполага, че притежателят е Angel, а при втория ако инициализираме с някакво име парите стават -1 (няма сведения за неговото богатство).
Идеята за тяхното написване беше да се покаже, че може да има повече от един едноаргументен конструктор, въпреки, че ако са повече могат да се инициализират само по начина в тази програма и третия, разгледан по-долу.
richman angel(100), peter("Peter");
При опит за инициализация по другия възприет начин
richman angel = 100, peter = "Peter"; // WRONG !!!
се издава съобщение от компилаторът
Cannot convert 'char *' to 'richman'.
Единствените два начина са най-горе показаният и този по-долу
richman angel = 100, peter("Peter");
Обърнете внимание, че даже да имате имате само един едноаргументен конструктор и той е от вида на втория (инициализация със стринг), то той не може да се инициализира с равенство
richman peter = "Peter"; // WRONG !!!
Отново се издава съобщение от компилаторът
Cannot convert 'char *' to 'richman'.
2. Преобразуване на клас на C string до наш клас за стрингове (Converting Strings to xStrings). В лекция 19, т. 6 въведохме наш клас xString, с който да поддържаме стрингове (това беше направено с обучителна цел, защото в същата лекция бе разгледан и класа string, който се поддържа от C++). Сега в тази програма ще въведем конструктор, така както е направено в превъзходния курс на Лафоор [1].
//
strcon.cpp
//
class models strings; uses constructors
#include
<iostream.h>
#include
<string.h>
// for strlen(), strcpy(), etc.
#include
<conio.h>
// for getch()
const int MAX = 80; // maximum length of xStrings
class
xString
{
private:
char str[MAX];
// ordinary C string
public:
xString()
// no-arg constructor
{
strcpy(str, ""); // make null string
}
xString(char s[]) // 1-arg
constructor
{
strcpy(str, s); // initialize
with string
}
void input()
// get string from user
{
cin.get(str, MAX);
}
void display()
// display string
{
cout << str;
}
void append(xString xs) // append argument string
{
if (strlen(str) + strlen(xs.str) < MAX-1)
strcat(str, xs.str);
else
cout << "\nError: xString too long" << endl;
}
};
void
main()
{
xString s2, s3;
// make xString objects
xString s1("Greetings, "); // make and initialize s1
cout << "Enter your name: ";
s2.input();
// get s2 from user
s1.append(s2); // append s2 to s1
s3 = s1; // set s3 to s1
s3.display(); // display s3
getch();
}
// main()
В класа xString има два конструктора - един без аргументи и един едноаргументен. Този без аргументи инициализира променливата на класа str с празен стринг "". Това е много полезно, защото ако това не се направи (съзнателно или не), то при отпечатване на str ще излизат случайни символи (това което е в паметта, отделена за променливата, чак до нулевия символ). И двата конструктора използват функцията strcpy(), но в едноаргументния конструктор тя копира аргумента s в променливата str.
! Както споменахме в лекция 31, масивите не могат да се инициализират в инициализиращия списък на конструктора, ето защо следващият запис е невалиден код:
xString(char s[]): str(s[]) // can’t do this -- s is an array
{ }
и компилаторът издава следното съобщение
[C++ Error] Expression syntax.
Аналогично и следният код е грешен
xString(char s[]): str(s) // WRONG !!!
{ }
Компилаторът издава следното съобщение
Cannot
convert 'char *' to 'char[80]'.
.
3. Превръщане
на числени стойности. Това
е още един пример, в който се използва едноаргументен конструктор за преобразуване
на стойности. Той е взет от курса на Лафоор [1]
и поддържа разстояние във футове и инчове.
//
englcon.cpp
//
demonstrates constructors with English class
#include
<iostream.h>
#include
<conio.h>
// for getch()
class
English
// English distances
{
private:
int feet;
float inches;
public:
// no-argument constructor
English() : feet(0), inches(0.0)
{ }
English(float meters)
// 1-argument constructor
{
const float MTF = 3.280839; // meters to feet
float fltfeet = MTF * meters; // get decimal feet
feet = int(fltfeet);
// integer part is feet
inches = 12 * (fltfeet-feet); // remainder is inches
}
English(int f, float i) :
// 2-argument constructor
feet(f), inches(i)
{ }
void display()
// display
{
cout << feet << "\'-" << inches << '\"';
}
};
void
main()
{
English E1(5, 2.5);
// call 2-arg constructor
cout << "\nE1 = ";
E1.display();
English E2(1.0);
// call 1-arg constructor
cout << "\nE2 = ";
E2.display();
English E3 = 2;
// call again 1-arg constructor
cout << "\nE3 = ";
E3.display();
E3 = E2;
cout << "\nE3 = ";
E3.display();
// you can also write
E3 = 3
// call again 1-arg constructor
cout << "\nE3 = ";
E3.display();
getch();
}
// main()
Класът English поддържа и работи с разстоянието във футове (променливата feet) и инчове (променливата inches) и има три конструктора - един без аргументи, който нулира разстоянието, един с един аргумент, който ще бъде разгледан по-подробно и един с два аргумента, които представляват футовете и инчовете. Разстояние от 5 фута и 2.5 инча се отбелязва като 5'-2.5".
! На български футовете се наричаха преди стъпки, а за инч преди се използваха думите дюйм от руски или цол от немски. Един фут е равен на 12 инча, а един инч е приблизително равен на 2.54 см. От друга страна един метър е равен на 3.280839 фута.
Едноаргументният конструктор приема разстояние в метри и го преобразува в двете променливи. За целта първо превръща разстоянието във футове, от него взима цялата част, след което намира остатъка му, който умножен по 12 дава инчовете.
В главната функция се създава един обект от класа, E1, който се инициализира с двуаргументния конструктор да е равен на 5'-2.5" и след това се показва на екрана. Създава се и обектът E2, който се иницилизира да е равен на един метър (редът English E2(1.0);), и разстоянието се показва на екрана (резултатът е 3'-3.37007"). След това се създава обектът E2, който се инициализира да е равен на два метра (редът English E3 = 2;) Обърнете внимание, че това става по друг начин, с оператора за присвояване, а не в скоби - но въпреки това пак е инициализиране. След показване на третия обект (резултатът е 6'-6.74014"), той се приравнява на втория и отново се показва на екрана.
! Обърнете внимание на последното присвояване:
E3 = 3 // call again 1-arg constructor
Това вече не е инициализация, а присвояване. Отново се извиква едноаргументния конструктор, чийто аргумент е от типа float.
Във функцията display() се използват т.н. специални символи (Escape Characters), част от които бяха разгледани в Таблица 2 на лекция 3. В тази функция, за да се отпечатат на екрана апострофът и кавичките, се поставя преди тях наклонена черта надясно, която е специален символ - "\'-" отпечатва апостроф, а '\"'отпечатва кавички на екрана.
Не винаги е необходимо такова преобразуване
с едноаргументен конструктор и то се прави само при класове, които представят
числени величини. В следващите лекции ще покажем още по-прегледен начин
за неговото извършване.
.
Keywords: С++,
OOP programming , C++ , Classes , Inheritance , Reusability , Creating
New Data Types , Polymorphism and Overloading
Ключови думи: клас
, обект, обектно ориентирано програмиране , полиморфизъм switch if else
?