साझा स्मृति मूल रूप से केवल पीओडी संरचनाओं (दिल में, उनके पास रचनाकार/प्रति/आदि हो सकती है ...) की अनुमति देता है।
Boost.Interprocess
साझा मेमोरी सेगमेंट में ऑफ़सेट के शीर्ष पर पॉइंटर्स सेमेन्टिक्स को अनुकरण करके बार बढ़ाता है।
हालांकि, एक आभासी सूचक शुद्ध डेटा के लिए सूचक नहीं है, यह कोड वर्गों के लिए एक सूचक है, और है कि जहां चीजें जटिल हो क्योंकि कोड वर्गों जरूरी एक से दूसरे प्रक्रिया से एक ही पते पर मैप नहीं कर रहे हैं (भले ही वे एक ही बाइनरी से लॉन्च किए गए हों)।
तो ... नहीं, वर्चुअल पॉइंटर्स-पॉलीमोर्फिक ऑब्जेक्ट्स साझा स्मृति में संग्रहीत नहीं किए जा सकते हैं।
हालांकि, सिर्फ इसलिए कि कई सी ++ कार्यान्वयन एक आभासी-सूचक प्रणाली का उपयोग करने के लिए इसका मतलब यह नहीं है कि इस बहुरूपी व्यवहार के लिए एक ही रास्ता है चुना है। उदाहरण के लिए, एलएलवीएम और क्लैंग में वे वर्चुअल पॉइंटर्स (और आरटीटीआई) के बिना पॉलिमॉर्फिज्म प्राप्त करने के लिए अपने बंद पदानुक्रमों पर निर्माण करते हैं ताकि स्मृति आवश्यकताओं को कम किया जा सके। उन वस्तुओं को प्रभावी रूप से साझा स्मृति में संग्रहीत किया जा सकता है।
तो, बहुरूपता साझा स्मृति के साथ संगत पाने के लिए: हम नहीं जरूरत टेबल/कार्यों के लिए संकेत स्टोर करने के लिए, लेकिन हम अनुक्रमित स्टोर कर सकते हैं।
विचार का उदाहरण, लेकिन शायद परिष्कृत किया जा सकता है।
/// In header
#include <cassert>
#include <vector>
template <class, size_t> class BaseT;
class Base {
template <class, size_t> friend class BaseT;
public:
int get() const; // -> Implement: 'int getImpl() const' in Derived
void set(int i); // = 0 -> Implement: 'void setImpl(int i)' in Derived
private:
struct VTable {
typedef int (*Getter)(void const*);
typedef void (*Setter)(void*, int);
VTable(): _get(0), _set(0) {}
Getter _get;
Setter _set;
};
static std::vector<VTable>& VT(); // defined in .cpp
explicit Base(size_t v): _v(v) {}
size_t _v;
}; // class Base
template <class Derived, size_t Index>
class BaseT: public Base {
public:
BaseT(): Base(Index) {
static bool const _ = Register();
(void)_;
}
// Provide default implementation of getImpl
int getImpl() const { return 0; }
// No default implementation setImpl
private:
static int Get(void const* b) {
Derived const* d = static_cast<Derived const*>(b);
return d->getImpl();
}
static void Set(void* b, int i) {
Derived* d = static_cast<Derived*>(b);
d->setImpl(i);
}
static bool Register() {
typedef Base::VTable VTable;
std::vector<VTable>& vt = Base::VT();
if (vt.size() <= Index) {
vt.insert(vt.end(), Index - vt.size() + 1, VTable());
} else {
assert(vt[Index]._get == 0 && "Already registered VTable!");
}
vt[Index]._get = &Get;
vt[Index]._set = &Set;
}
}; // class BaseT
/// In source
std::vector<VTable>& Base::VT() {
static std::vector<VTable> V;
return V;
} // Base::VT
int Base::get() const {
return VT()[_v]._get(this);
} // Base::get
void Base::set(int i) {
return VT()[_v]._set(this, i);
} // Base::set
ठीक है ... मुझे लगता है कि है कि अब आप उपयोग के बारे में संकलक का जादू ...
सराहना करते हैं, यह सौभाग्य से बहुत सरल है:
/// Another header
#include <Base.h>
// 4 must be unique within the hierarchy
class Derived: public BaseT<Derived, 4> {
template <class, size_t> friend class BaseT;
public:
Derived(): _i(0) {}
private:
int getImpl() const { return _i; }
void setImpl(int i) { _i = i; }
int _i;
}; // class Derived
ideone पर
कार्रवाई में।
महान, मैं वास्तव में क्या उम्मीद। धन्यवाद! – Queequeg
@Queequeg: दिलचस्प बात यह है कि मैंने पॉलीमोर्फिक ऑब्जेक्ट्स के साथ साझा मेमोरी के नामित सेगमेंट का उपयोग देखा है। इस विशेष मामले में एक एकल प्रक्रिया कभी भी सेगमेंट तक पहुंचती है (साथ ही) और साझा मेमोरी सेगमेंट का उपयोग किया जाता है ताकि प्रक्रिया को क्रैश करना चाहिए, इसे फिर से शुरू करने पर इसकी सभी स्थिति वापस मिल सकती है। इसमें सभी आभासी पॉइंटर्स को फिर से लिखना शामिल है, इसलिए यह निश्चित रूप से शामिल है। –