Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.
Например, ниже - класс ученика, который будет использовать его в нашем коде.
public class Student {
private int id;
public int getId() {
return this.id;
}
public setId(int newId) {
this.id = newId;
}
}
Приведенный ниже код дает вам исключение с нулевым указателем.
public class School {
Student obj_Student;
public School() {
try {
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
Поскольку вы используете Obj_Student
, но вы забыли инициализировать его, как в правильном коде, показанном ниже:
public class School {
Student obj_Student;
public School() {
try {
obj_Student = new Student();
obj_Student.setId(12);
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
class mul
{
public:
mul(int p1, int p2)
{
param1 = p1;
param2 = p2;
}
operator int ()
{
return param1 * param2;
}
operator std::string ()
{
return std::string(param2, param1 + '0');
}
private:
int param1;
int param2;
};
Не то, чтобы я использовал бы это.
Hmmm, следующий статья проекта кода, кажется, делает то, что Вы после. Должно быть волшебным;)
Вы могли сделать что-то как
template<typename T>
T mul(int i,int j){
return i * j;
}
template<>
std::string mul(int i,int j){
return std::string(j,i);
}
И затем назвать его как это:
int x = mul<int>(2,3);
std::string s = mul<std::string>(2,3);
нет никакого способа перегрузиться на возвращаемом значении.
Поместить его в различное пространство имен? Это было бы то, как я сделаю это. Не строго перегрузка, скорее справедливое наличие двух методов с тем же именем, но различного объема (следовательно:: оператор разрешения области видимости).
Так stringnamespace:: mul и intnamespace:: mul. Возможно, не действительно, что Вы спрашиваете, но это походит на единственный способ сделать это.
Вы могли использовать шаблон, но тогда необходимо будет определить шаблонный параметр при совершении вызова.
Можно использовать решение для функтора выше. C++ не поддерживает это для функций за исключением константы. Можно перегрузиться на основе константы
Не в C++. То, что Вы вошли бы в вышеупомянутый пример, будет возвращенным значением, которое является международным броском во что-то string
, может понять, скорее всего, char
. Который был бы ASCII 18 или "управлением устройствами 2".
Насколько я знаю, Вы не можете (большая жалость, хотя...). Как обходное решение, можно определить параметр и перегрузка что один.
Я предполагаю, что у Вас мог быть он, возвращают некоторый странный тип Foo, который просто получает параметры, и затем у Foo есть неявный интервал оператора и строка оператора, и это "работало" бы, хотя это не будет действительно перегружаться, скорее неявный прием преобразования.
Вы не можете перегрузить функцию на основе возвращаемого значения только.
Однако, в то время как строго говоря это не перегруженная функция, Вы могли возвратить из своей функции в результате экземпляр класса, это перегружает операторы преобразования.
Позвольте mul быть классом, mul (x, y) его конструктор и перегрузка некоторые операторы кастинга.
Используйте неявное преобразование в промежуточном классе.
class BadIdea
{
public:
operator string() { return "silly"; }
operator int() { return 15; }
};
BadIdea mul(int, int)
Вы получаете идею, ужасную идею все же.
Нет.
Вы не можете перегрузиться возвращаемым значением, потому что вызывающая сторона может сделать что-либо (или ничто) с ним. Рассмотрите:
mul(1, 2);
возвращаемое значение просто выброшено, таким образом, нет никакого способа, которым оно могло выбрать перегрузку на основе одного только возвращаемого значения.
Если Вы хотели сделать mul
, реальная функция вместо класса, Вы могли бы просто использовать промежуточный класс:
class StringOrInt
{
public:
StringOrInt(int p1, int p2)
{
param1 = p1;
param2 = p2;
}
operator int ()
{
return param1 * param2;
}
operator std::string ()
{
return std::string(param2, param1 + '0');
}
private:
int param1;
int param2;
};
StringOrInt mul(int p1, int p2)
{
return StringOrInt(p1, p2);
}
Это позволяет Вам сделать вещи как передача mul
как функция в алгоритмы станд.:
int main(int argc, char* argv[])
{
vector<int> x;
x.push_back(3);
x.push_back(4);
x.push_back(5);
x.push_back(6);
vector<int> intDest(x.size());
transform(x.begin(), x.end(), intDest.begin(), bind1st(ptr_fun(&mul), 5));
// print 15 20 25 30
for (vector<int>::const_iterator i = intDest.begin(); i != intDest.end(); ++i)
cout << *i << " ";
cout << endl;
vector<string> stringDest(x.size());
transform(x.begin(), x.end(), stringDest.begin(), bind1st(ptr_fun(&mul), 5));
// print 555 5555 55555 555555
for (vector<string>::const_iterator i = stringDest.begin(); i != stringDest.end(); ++i)
cout << *i << " ";
cout << endl;
return 0;
}
Необходимо сказать компилятор который версия использовать. В C++ можно сделать это три пути.
, Вы несколько обманули, потому что Вы отправили целое число в функцию, ожидающую символа, и неправильно отправили номер шесть, когда символьное значение '6' не 6, но 54 (в ASCII):
std::string mul(char c, int n) { return std::string(n, c); }
std::string s = mul(6, 3); // s = "666"
правильное решение было бы, конечно,
std::string s = mul(static_cast<char>(54), 3); // s = "666"
Это стоило упомянуть, я предполагаю, даже если Вы не хотели решения.
, можно добавить, что фиктивный параметр каждому функционирует, таким образом вынуждая компилятор выбрать правильные функции. Самый легкий путь состоит в том, чтобы отправить ПУСТОЙ фиктивный указатель типа, желаемого для возврата:
int mul(int *, int i, int j) { return i*j; }
std::string mul(std::string *, char c, int n) { return std::string(n, c); }
, Который может использоваться с кодом:
int n = mul((int *) NULL, 6, 3); // n = 18
std::string s = mul((std::string *) NULL, 54, 3); // s = "666"
С этим решением, мы создаем "фиктивную" функцию с кодом, который не скомпилирует, если инстанцировано:
template<typename T>
T mul(int i, int j)
{
// If you get a compile error, it's because you did not use
// one of the authorized template specializations
const int k = 25 ; k = 36 ;
}
Вы отметите, что эта функция не скомпилирует, который является хорошей вещью, потому что мы хотим только использовать некоторые ограниченные функции через шаблонную специализацию:
template<>
int mul<int>(int i, int j)
{
return i * j ;
}
template<>
std::string mul<std::string>(int i, int j)
{
return std::string(j, static_cast<char>(i)) ;
}
Таким образом, следующий код скомпилирует:
int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>(54, 3); // s = "666"
, Но этот не будет:
short n2 = mul<short>(6, 3); // error: assignment of read-only variable ‘k’
Эй, Вы обманули, также!
Право, я действительно использовал те же параметры для двух "перегруженных" функций. Но Вы действительно запускали обман (см. выше)...
^_^
более серьезно, если у Вас должны быть различные параметры, тогда Вы желание записать больше кода, и затем иметь для явного использования правильных типов при вызывании функций для предотвращения неоднозначностей:
// For "int, int" calls
template<typename T>
T mul(int i, int j)
{
// If you get a compile error, it's because you did not use
// one of the authorized template specializations
const int k = 25 ; k = 36 ;
}
template<>
int mul<int>(int i, int j)
{
return i * j ;
}
// For "char, int" calls
template<typename T>
T mul(char i, int j)
{
// If you get a compile error, it's because you did not use
// one of the authorized template specializations
const int k = 25 ; k = 36 ;
}
template<>
std::string mul<std::string>(char i, int j)
{
return std::string(j, (char) i) ;
}
И этот код использовался бы как таковой:
int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>('6', 3); // s = "666"
И следующая строка:
short n2 = mul<short>(6, 3); // n = 18
все еще не скомпилировал бы.
я люблю C++...
:-p
Хорошо, вы гении;) вот как вы это делаете профи.
class mul
{
int m_i,m_j;
public:
mull(int i,int j):m_i(i),m_j(j){}
template
operator R()
{
return (R)m_i * m_j;
}
};
используйте как
double d = mul(1,2);
long l = mul(1,2);
no stupid <>