Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
static const int ONE = 1;
static const int TWO = 2;
const int SwitchClass::ONE = 1;
const int SwitchClass::TWO = 2;
class SwitchClass
{
public:
static const int ONE = 1; // являются интегральными константами времени компиляции по стандарту
static const int TWO = 2;
....
};
constexpr
3. Соответствует стандарту C++, причем это такой типичный пример, что все, по-моему, о нем знают, даже если ни разу не сталкивались лично.class TestVirtualsChild : public TestVirtuals
{
public:
using TestVirtuals::fun; // решается этой строчкой
virtual void fun(int i)
{
std::cout<<"int child"<<std::endl;
}
};
class TestVirtuals
{
public:
void fun(int i)
{
doFun(i);
}
void fun(float f)
{
doFun(f);
}
void fun(std::string s)
{
std::cout<<"string"<<std::endl;
}
private:
virtual void doFun(int i)
{
std::cout<<"int"<<std::endl;
}
virtual void doFun(float f)
{
std::cout<<"float"<<std::endl;
}
};
class TestVirtualsChild : public TestVirtuals
{
private:
virtual void doFun(int i)
{
std::cout<<"int child"<<std::endl;
}
};
int show(const char* s, int x) { puts(s); return x; }
int main()
{
show("one",1) + show("two",2); // one two или two one - как повезёт
show("one",1) & (show("two",2) + show("three",3)); // one two three в любом порядке
show("one",1) && (show("two",2) + show("three",3)); // сперва one, затем two three в любом порядке
int x = 1;
x++ & ++x; // undefined behavior
x++ && ++x; // well-defined
x++ && (++x & x++); // снова undefined
}
#include <cstdio>
struct Condition // захотели мы сделать свой логический класс (или, например, указатель)
{
bool c;
explicit Condition(bool c) : c(c) { printf("ctor "); }
operator bool() const { printf("oper "); return c; } // который приводится к штатному булеву типу
};
bool foo() { printf("foo "); return true; }
bool bar() { printf("bar "); return false; }
bool pass(bool v) { printf("\n"); return v; }
bool a = pass( Condition(foo()) && Condition(bar()) ); // foo ctor oper bar ctor oper
bool b = pass( Condition(bar()) && Condition(foo()) ); // bar, ctor, oper
// потом решили, а зачем нам приведение, если мы можем оставаться на уровне Condition
Condition operator&& (Condition const& x, Condition const& y)
{
printf("and ");
return Condition(x.c && y.c);
}
bool c = pass( Condition(foo()) && Condition(bar()) ); // bar ctor foo ctor and ctor oper
bool d = pass( Condition(bar()) && Condition(foo()) ); // foo ctor bar ctor and ctor oper
int main()
{
return a+b+c+d;
}
Но rvalue может неявно привестись только к константному lvalue (iterator const&), либо к временному (iterator&&).
vector<T>::iterator это класс, а в компиляторе автора скорее всего T*.struct A {};
A foo() { return A(); } // можно и просто конструктор передавать
void bar(A&) {}
void buz(A&&) {} // только для С++03 и выше
int main()
{
bar(foo()); // любой VC сожрёт, любой gcc выругается
buz(foo()); // все современные компиляторы сожрут
}
void buz(A&&) {} // только для С++03 и выше
const_iterator — но это «константный итератор» не в том смысле, что он сам является константой, а в том смысле что он, в отличии от просто iterator, не позволяет изменить то, на что он указывает.If the vector object is const-qualified, the function returns a const_iterator. Otherwise, it returns an iterator.
В данном случае, возвращается const_iterator
vector<int>::iterator, это можно проверить в отладчике. nickolaym действительно правильно объяснил (за одним исключением, добавлю ему коммент), проблема в том, что begin возвращает временный объект, от которого хотят lvalue reference.struct A { int x; };
struct B {
int y;
void whoami() { printf("%p\n", (void*)this); }
};
struct C : A, B {};
void test(C* pc)
{
pc->whoami();
B* pb = pc;
pb->whoami();
}
int main()
{
test(0); // 00000004 00000000
test(new C); // 0002F7F4 0002F7F4
}
Мораль. Функции, выполняющие какие-то побочные действия, в логических выражениях лучше не использовать. Чтобы гарантировать вызов обеих функций с сохранением результата, код листинга 3 нужно переписать следующим образом
bool update1Result = update1(); bool update2Result = update2(); bool updatedSuccessfully = update1Result && update2Result ;
if (update1() & update2()) { ... }if (!!update1() & !!update2()) { ... } Но лучше, конечно, писать более очевидно…#define bool int, речь не об этом.#include <cstdio>
#define WHOAMI() printf("%s\n", __PRETTY_FUNCTION__) // __FUNCSIG__ для MSVC
struct A
{
void f() { WHOAMI(); }
virtual void f(int) { WHOAMI(); }
};
struct B : A
{
void f(const char*) { WHOAMI(); } // перегрузкой сокрыли унаследованные сигнатуры
// using A::f; // вот так можно открыть их обратно
};
struct C : B
{
void f(int) { WHOAMI(); } // перегрузкой сокрыли имена, переопределением заменили виртуальную функцию
// using B::f;
};
int main()
{
C c;
c.A::f(); // квалифицированный доступ - не помеха сокрытию
c.B::f("hello");
A& a = c;
a.f(123); // виртуальная функция действительно переопределена
}
var success = preprocess()
&& checkRequisites()
&& doStuff(a, b)
&& doOtherStuff()
&& finalize();
&&, || и ?: «экономные». Того, что не нужно вычислять, не вычисляют.[ -d $file ] && work_with_dir $file || work_with_file $file
// count - число элементов, sum - их сумма
bool average_more_than_one = (count > 0) && (float(sum)/count > 1.f);
наткнулись на багу VS2005 — после 128-го вложенного if-else-if условия просто напросто игнорируются. Пришлось переделать в switch-case
using TestVirtuals::fun;По всей видимости, считается, что float не является точным типом, потому и нуля как такового в нем представлено быть не может.
endl.Конечно, остается вопрос «Зачем делать метод, не использующий свойства объекта, нестатическим».Метод может использовать свойства объекта, но не при каждом вызове, в зависимости от аргументов, параметров шаблона, значений глобальных переменных или внешних функций (rand(), к примеру). Будут ли использованы свойства объекта, может зависеть и от класса-наследника, к которому принадлежит объект, если данный метод виртуальный или вызывает виртуальные методы, но в данном случае произойдет сбой уже при попытке вызвать виртуальный метод, так как указатель vptr тоже является свойством объекта.
Шесть загадок по С++