#include<iostream>
using namespace std;
class String
{
protected:
enum {SZ= 80};
char str[SZ];
public:
String (){str[0]='\0';}
String(char s[])
{
strcpy(str,s);
}
void display() const
{
cout<<str;
}
operator char*()
{
return str;
}
};
class Pstring : public String
{
public:
Pstring(char s[])
{
if (strlen(s)>SZ-1)
{
for(int j=0;j<SZ-1;j++)
{
str[j]=s[j];
}
str[SZ-1]='\0';
}
else
{String(s);}
}
};
int main()
{
Pstring s2 = "This is a strong string.";
cout<<"\ns2 = "; s2.display();
return 0;
}
s2.display()
возвращает пустое значение. При отладке обнаруживается, что String(s)
в Pstring вызывает конструктор без аргументов в классе String. Я понимаю это как конструктор с одним аргументом, и поэтому String(char s[])
должен был быть вызван. Что это за поведение?
String
, который выполняет любую операцию ввода-вывода, является очень плохим кодом (принцип единой ответственности).
Включение большего количества предупреждений дает «предупреждение: ненужные скобки в объявлении 's'». Кроме того, вы не можете вызвать конструктор; язык делает это за вас при создании объекта.
остерегайтесь String(char s[])
ctor: если входная строка длиннее 80, вы испортите память
Этот фрагмент кода
else
{String(s);}
не имеет смысла.
Эта линия
String(s);
является объявлением переменной s
типа String
с областью действия составного оператора else части оператора if.
Обратите внимание на то, что этот конструктор
Pstring(char s[])
неявно вызывает конструктор по умолчанию класса String, прежде чем управление будет передано в тело конструктора. То есть тело конструктора получает управление только после того, как будут созданы все подобъекты создаваемого объекта производного класса.
Вы должны разместить проверку переданной строки в конструкторе класса String
.
Например, в классе String
вы можете определить конструктор с параметром следующим образом
String( const char s[] )
{
strncpy( str, s, SZ );
str[SZ - 1] = '\0';
}
И конструктор в производном классе может быть определен как
Pstring( const char s[] ) : String( s )
{
}
Почему `Pstring(char s[])` вызывает конструктор класса String. Я имею в виду, что нет списка инициализации. Не должно ли оно сначала войти в тело самого себя?
@WaqarAhmed Сначала создаются объекты класса, включая подобъекты его базового класса, и только после этого тело конструктора производного класса получает управление.
Вы можете инициализировать базовый класс только с помощью списка инициализаторов.