using ve Namespace (İsim Alanı)
using kelimesi eskiden beri namespace'leri dahil etmek için kullanılır. namespace scope, yani isim etki alanı şöyledir. A'yı dahil eden her bir B translation unit', A'nın değişken, metod ve sınıflarına erişebilir.
Bazen kodlarda namespace'ten önce :: karakterini görebiliriz. Yani kod şuna benzeyebilir.
Ata sınıfta normalde erişemediğimiz metodlara erişebilmemizi sağlar. Bu yöntem aynı zamanda Inheriting Constructor için de kullanılır. Bu konu için C++11 ile Constructor Inheritance yazısına bakınız.
Örnek
Şöyle yaparız.
using anahtar kelimesi typedef olarak kullanılabilir. Açıklaması şöyle.
unnamed struct için şöyle yaparız.
using aynı typedef gibi kullanılabiliyor ve dolayısıyla typdef uyumluluğunda karşımıza çıkan problemin aynısı burada da görülebilir.
Örnek
Şöyle yaparız.
using kelimesi eskiden beri namespace'leri dahil etmek için kullanılır. namespace scope, yani isim etki alanı şöyledir. A'yı dahil eden her bir B translation unit', A'nın değişken, metod ve sınıflarına erişebilir.
namespace A { \
int i = 9; | <-- namespace A scope.
} /
namespace B { \
using namespace A; | <-- namespace B scope. "i" is visible after
void bar() | the "using namespace" line.
{ |
i += 1; /*Ok*/ |
} |
} /
namespace B { \
void foo() |
{ | <-- still namespace B scope. "i" is still visible
i += 1; /*Ok*/ |
} |
}
using ::std:: veya using ::mynamespaceBazen kodlarda namespace'ten önce :: karakterini görebiliriz. Yani kod şuna benzeyebilir.
using std::...;
veyausing ::std::...;
Bu kullanım şekli farklı namespace'ler içindeki sınıf isimlerinin çakışması yüzünden oluyor. Eğer using ::std yaparsak en tepedeki namespace içindeki bir şeyi kullanmak istediğimizi belirtiriz. Tabiki std içindeki sınıfları kullanmamak gerekir. Dolayısıyla kendi kodlarımızda da çakışma olabileceğini düşünerek şöyle bir örnek verebiliriz.namespace A
{
namespace B
{
class C;
}
}
namespace B
{
class C;
}
namespace A
{
using B::C; // resolves to A::B::C
using ::B::C; // resolves to B::C
// (note that one of those using declarations has to be
// commented for making this valid code!)
}
using ve Ata Sınıf - c++11Ata sınıfta normalde erişemediğimiz metodlara erişebilmemizi sağlar. Bu yöntem aynı zamanda Inheriting Constructor için de kullanılır. Bu konu için C++11 ile Constructor Inheritance yazısına bakınız.
Örnek
Şöyle yaparız.
struct Base
{
int foo(int);
int foo(int, int);
};
struct Child : Base
{
using Base::foo; //Her iki foo metodu erişilir hale gelir
int foo(int, int, int);
};
Kullanmak için şöyle yaparız.Child c;
c.Base::foo(0, 0);
Eğer bir overload metodu tekrar erişilemez yapmak istersek şöyle yaparız.struct Base
{
int foo(int);
int foo(int, int);
};
struct Child : Base
{
using Base::foo;
int foo(int, int) = delete;
int foo(int, int, int);
};
using ve typdef - c++11using anahtar kelimesi typedef olarak kullanılabilir. Açıklaması şöyle.
Söz dizimi şöyle.A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. Such a typedef-name has the same semantics as if it were introduced by the typedef specifier.
using <typedef-name> = <type>;
Şununla aynı şeydir.typedef <type> <typedef-name>;
Örnekunnamed struct için şöyle yaparız.
using S = struct { int x; }
using Tip Uyumluluğu - c++11using aynı typedef gibi kullanılabiliyor ve dolayısıyla typdef uyumluluğunda karşımıza çıkan problemin aynısı burada da görülebilir.
Örnek
Şöyle yaparız.
using PortalId = std::string;
using CakeId = std::string;
PortalId portal_id("2");
CakeId cake_id("is a lie");
portal_id = cake_id; // OK
Çözümlerden bir tanesi kalıtım ile farklı bir sınıf tanımlamak. Ben bu yöntemi sevmiyorum. Şöyle bir macro tanımlarız.#define SAFE_TYPEDEF(Base, name) \
class name : public Base { \
public: \
template <class... Args> \
explicit name (Args... args) : Base(args...) {} \
const Base& raw() const { return *this; } \
};
Daha sonra farklı sınıflar elde ettiğimiz için derleyici bizim için karışıklıkları yakalar.SAFE_TYPEDEF(std::string, PortalId);
SAFE_TYPEDEF(std::string, CakeId);
int main()
{
PortalId portal_id("2");
CakeId cake_id("is a lie");
std::map<CakeId, PortalId> p_to_cake; // OK
p_to_cake[cake_id] = portal_id; // OK
p_to_cake[portal_id] = cake_id; // COMPILER ERROR
portal_id = cake_id; // COMPILER ERROR
portal_id = "1.0"; // COMPILER ERROR
portal_id = PortalId("42"); // OK
return 0;
}
İkinci yöntem ise farklı tag'ler ile template tanımlamak. Şöyle bir template ve tagler tanımlarız.#include <iostream>
#include <string>
#include <map>
// define some tags to create uniqueness
struct portal_tag {};
struct cake_tag {};
// a string-like identifier that is typed on a tag type
template<class Tag>
struct string_id
{
// needs to be default-constuctable because of use in map[] below
string_id(std::string s) : _value(std::move(s)) {}
string_id() : _value() {}
// provide access to the underlying string value
const std::string& value() const { return _value; }
private:
std::string _value;
// will only compare against same type of id.
friend bool operator < (const string_id& l, const string_id& r) {
return l._value < r._value;
}
};
Daha sonra farklı tag'ler kullandığımız için derleyici bizim için karışıklıkları yakalar.// create some type aliases for ease of use
using PortalId = string_id<portal_tag>;
using CakeId = string_id<cake_tag>;
using namespace std;
// confirm that requirements are met
auto main() -> int
{
PortalId portal_id("2");
CakeId cake_id("is a lie");
std::map<CakeId, PortalId> p_to_cake; // OK
p_to_cake[cake_id] = portal_id; // OK
// p_to_cake[portal_id] = cake_id; // COMPILER ERROR
// portal_id = cake_id; // COMPILER ERROR
// portal_id = "1.0"; // COMPILER ERROR
portal_id = PortalId("42"); // OK
return 0;
}
Hiç yorum yok:
Yorum Gönder